// 事件处理器
const Event = (function(){
        
    let _eventList = {};

    let namespace = "default";

    var event = {
        _eventList,
        // 添加事件监听
        on(eventName,execute,alias){
            if(!_eventList[namespace]){
                _eventList[namespace] = {};
            }
            if(!_eventList[namespace][eventName]){
                _eventList[namespace][eventName] = [];
            }
            if(!alias){
                alias = "default"
            }
            _eventList[namespace][eventName].push({
                alias,
                execute
            });
            // namespace = "default";
        },

        // 取消事件监听
        off(eventName,execute){
            if(!_eventList[namespace] || !_eventList[namespace][eventName]){
                return;
            }
            for(let i = 0; i < _eventList[namespace][eventName].length; i++){
                if(_eventList[namespace][eventName][i].execute == execute){
                    _eventList[namespace][eventName].splice(i--,1);
                    return true;
                }
            }
            // namespace = "default";
        },

        // 通过别名取消事件
        aliasOff(eventName,alias){
            if(!_eventList[namespace] || !_eventList[namespace][eventName]){
                return false;
            }
            for(let i = 0; i < _eventList[namespace][eventName].length; i++){
                if(_eventList[namespace][eventName][i].alias == alias){
                    _eventList[namespace][eventName].splice(i--,1);
                    return true;
                }
            }
        },

        // 命名空间
        useSpace(name){
            return {
                on(eventName,fun){
                    namespace = name;
                    event.on(eventName,fun);
                    namespace = "default";
                },
                off(eventName,fun){
                    namespace = name;
                    event.off(eventName,fun);
                    namespace = "default";
                },
                aliasOff(eventName,alias){
                    namespace = name;
                    event.aliasOff(eventName,alias);
                    namespace = "default";
                },
                trigger(eventName,...args){
                    namespace = name;
                    event.trigger(eventName,...args);
                    namespace = "default";
                }
            };
        },

        // 触发事件
        trigger(eventName,...args){
            if(!_eventList[namespace] || !_eventList[namespace][eventName]){
                return;
            }
            _eventList[namespace][eventName].forEach(event=>event.execute.apply(this,args));
        }
    }

    return event;
})();

// 配置文件
const styleConfig = {
    pin:{
        color:{
            t:"#b34141",
            ts_t:"#990066",
            ts_b:"#990066",
            tp_t:"#CCCCFF",
            tp_b:"#CCCCFF",
            
            i:"#99CCCC",
            is_t:"#990066",
            is_b:"#990066",
            ip_t:"#CCCCFF",
            ip_b:"#CCCCFF",
            
            b:"#336699",
            bs_t:"#990066",
            bs_b:"#990066",
            bp_t:"#CCCCFF",
            bp_b:"#CCCCFF",
            
            drill:"#CCCCCC",//过孔颜色
            contour:"#99CCCC",   //pin描边颜色 
        }
    },
    layer:{
        st:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        sb:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        at:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        ab:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        sm_t:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        sm_b:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        et:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        eb:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        bt:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        bb:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        pt:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        },
        pb:{
            text:{
                color_text:"black",//文字颜色
                color_border:"red",//文字范围
                typeface:"微软雅黑",//字体
                text_size:"10",//字号
            },
            path:{
                color_line:"#1a2273",//线颜色
                line_width:1,//线宽
            },
            shape:{
                color_fill:"green",//铜皮填充颜色
                color_out:"#83b31e",//铜皮镂空部分颜色 
                color_line:"while",//描边颜色
                line_width:1,//线宽
            },  
        }
    },
    color_origin:"#a4bfa4",     //原点颜色
    typeface:"微软雅黑",            //全局字体 
    text_size:"20px",           //全局字号
    line_width:1,               //线宽
    txt_color:"black",
    
    highlight_color:"#ffbc00bd",  //强调的颜色
    highlight_scope:10,           //强调的范围
    grid_color:"#c0c0c0",       //格点颜色
}

// 获取属性的类型
function getRawType(value){
    return Object.prototype.toString.call(value).slice(8,-1);
}

// 图形处理工具
const figureUtil = {
    // 圆矩转路径
    cs2Path(cs){
        let r = cs.r;
        let originR = r;
        let w = cs.w;
        let h = cs.h;
        let x = 0, y=0;
        let arc_r = r < 0 ? "nil" : "t";
        r = Math.abs(r);
        var x1 = x - (w/2 - r),
            y1 = y+ h/2,
            x2 = x + (w/2 - r),
            y2 = y1,

            j1_x= x + w / 2 - r,   
            j1_y = y1 - r,   
                            
            x3 = x2 + r,      
            y3 = y2 - r,

            x4 = x3,

            y4 = y - (h/2 - r),

            j2_x = x4 - r,   
            j2_y = y4,   
                            
            x5 = x4 - r,        
            y5 = y4 - r,

            x6 = x - (w/2 - r),
            y6 = y5,

            j3_x = x6,
            j3_y = y6 + r,
            
            x7 = x6 - r,
            y7 = y6 + r,

            x8 = x7,
            y8 = y + (h/2 -r),

            j4_x = x8 + r,
            j4_y = y8;

        if(originR<0){
            j1_x = x + w / 2,   
            j1_y = y + h / 2,   
            j2_x = x + w / 2,   
            j2_y = y - h / 2,   
            j3_x = x - w / 2,
            j3_y = y - h / 2,
            j4_x = x - w / 2,
            j4_y = y + h / 2;
        }
        
        let path = [];
        path.push(this.point2Line([x1,y1],[x2,y2]));
        path.push(this.point2Arc([x2,y2],[x3,y3],[j1_x,j1_y],r,arc_r));
        path.push(this.point2Line([x3,y3],[x4,y4]));
        path.push(this.point2Arc([x4,y4],[x5,y5],[j2_x,j2_y],r,arc_r));
        path.push(this.point2Line([x5,y5],[x6,y6]));
        path.push(this.point2Arc([x6,y6],[x7,y7],[j3_x,j3_y],r,arc_r));
        path.push(this.point2Line([x7,y7],[x8,y8]));
        path.push(this.point2Arc([x8,y8],[x1,y1],[j4_x,j4_y],r,arc_r));
        let pathData = {
            form:"PATH",
            skewing_x:cs.skewing_x,
            skewing_y:cs.skewing_y,
            rotate:cs.rotate,
            path
        };
        return pathData;
    },

    // point2Line 路径点转线
    point2Line(point1,point2,width){
        let line = {
            st_x:point1[0],
            st_y:point1[1],
            sp_x:point2[0],
            sp_y:point2[1],
            width:width || 0,
            name:"LINE",
            arc_r:"nil",
            o_x: 0,
            o_y: 0,
            r:0
        }
        return line;
    },

    // point2Arc 路径点转弧
    point2Arc(point1,point2,oPoint,r,dir,width){
        let arc = {
            st_x:point1[0],
            st_y:point1[1],
            sp_x:point2[0],
            sp_y:point2[1],
            width:width || 0,
            name:"ARC",
            arc_r:dir || "nil",
            o_x: oPoint[0],
            o_y: oPoint[1],
            r:r
        };
        return arc;
    },
}

const util = {
    
    // 节流器
    throttle(func,interval,fixedThis){
        var saveArgus,
            saveThis,
            isThrottle = false;

        function worker(){
            if(isThrottle){
                saveArgus = arguments;
                saveThis = fixedThis || this;
                return;
            }

            func.apply(this,arguments);
            
            isThrottle = true;

            setTimeout(()=>{
                isThrottle = false;
                if(saveArgus){
                    worker.apply(saveThis,saveArgus);
                    saveThis = saveArgus = null;
                }
            },interval || 16);
        }

        return worker;
    },

    // 防抖
    antiShake(fn,interval,self){
        let timer = 0;
        return function (...args){
            if(timer){
                clearTimeout(timer);
            }
            timer = setTimeout(()=>{
                fn.apply(self,args);
            },interval || 100);
        }
    },

    /**
     * 
     * @param {HTMLElement|string} parent
     * @returns
     */
    getElement(parent){
        if(typeof parent === "string"){
            let ele = document.querySelector(parent);
            return ele;
        }else{
            if(parent instanceof HTMLElement){
                return parent;
            }
            return false;
        }
    },

}

// 判断点是否在图形上
const pointInFigure = {
    /**
     * 判断点是否在圆内
     * @param {{x:number,y:number}} point -- 点的坐标
     * @param {{x:number,y:number,r:number}} img -- 圆的信息
     * @returns 
     */
    inCircle(point,circle){
        let dis = Math.sqrt(Math.pow(point.x - circle.x,2) + Math.pow(point.y - circle.y,2));
        return dis <= circle.r/2;
    },

    // 判断图形是否在一封闭路径内
    inClosedPath(point,paths){
        var inside = false;
        for(let i = 0,l = paths.length; i < l ; i++){
            let linePoint1 = paths[i];
            let linePoint2 = i == l - 1 ? paths[0] : paths[i+1];
            let slope = (linePoint2.y - linePoint1.y) / (linePoint2.x - linePoint1.x);
            // 判断点是否在线段的x轴之间
            let betweenX = (linePoint1.x < point.x && linePoint2.x > point.x) || (linePoint1.x > point.x && linePoint2.x < point.x);
            // 以point作一条平行于Y轴的射线，判断射线与经过linePoint1和linePoint2两点的直线的交点,是否位于point的y轴的上方
            let intersect = point.y < (slope * (point.x - linePoint1.x) + linePoint1.y);
            
            if(betweenX && intersect){
                inside = !inside;
            }
        }
        return inside;
    },

    // 是否在线上
    inLine(point,line){
        // 计算线条的斜率
        let rectData = []
        if(line.st_x == line.sp_x || line.st_y == line.sp_y){
            rectData.push({
                x: line.st_x + line.width / 2,
                y: line.st_y + line.width / 2
            });
            rectData.push({
                x: line.sp_x + line.width / 2,
                y: line.sp_y + line.width / 2
            });
            rectData.push({
                x: line.sp_x - line.width / 2,
                y: line.sp_y - line.width / 2
            });
            rectData.push({
                x: line.st_x - line.width / 2,
                y: line.st_y - line.width / 2
            });
        }else{
            let k = (line.st_y - line.sp_y) / (line.st_x - line.sp_x);
            let slope = -1/k;
            // x = x1±Math.sqrt(d/(k^2+1));
            let base = Math.sqrt(Math.pow(line.width / 2,2) / (slope * slope + 1));
            let point1 = {
                x: line.st_x + base,
                y: base * slope + line.st_y,
            }
            let point2 = {
                x: line.st_x - base,
                y: -base * slope + line.st_y,
            }
            let point3 = {
                x: base + line.sp_x,
                y: base * slope + line.sp_y,
            }
            let point4 = {
                x: line.sp_x - base,
                y: -base * slope + line.sp_y,
            }
            rectData.push(point1);
            rectData.push(point3);
            rectData.push(point4);
            rectData.push(point2);
        }
        return this.inClosedPath(point,rectData);
    },

    // 是否在弧上
    inArc(point,arc){
        let x = point.x,y = -point.y;
        let status=false,
            r=arc.r,
            st_x=arc.st_x,
            st_y=-arc.st_y,
            sp_x=arc.sp_x,
            sp_y=-arc.sp_y,
            line_w=arc.width/2,
            o_x=arc.o_x,
            o_y=-arc.o_y,
            dir=arc.arc_r,
            rot = arc.rotate;
        let gap=Math.sqrt((Math.pow(x-o_x,2)+Math.pow(y-o_y,2)));
        if(r-line_w<gap&&gap<r+line_w){//满足圆的方程
            let median=sountAngle(x-o_x ,  y-o_y),
                st = sountAngle(st_x-o_x, st_y-o_y),
                sp = sountAngle(sp_x-o_x, sp_y-o_y);
            //计算夹角
            let angle_ref=[],
                angle_acc=[],
                angle_st=180*st.angle/Math.PI,
                angle_me=180*median.angle/Math.PI,
                angle_sp=180*sp.angle/Math.PI;
            angle_ref=[angle_st,angle_sp];
            let maxAngle=Math.max.apply(null,angle_ref),
                minAngle=Math.min.apply(null,angle_ref);
            if(st_x==sp_x&&st_y==sp_y){
                status=true;
            }else{
                //判断夹角是否过0点
                let angle_lock=false,
                    qua_st=st.qua,
                    qua_sp=sp.qua;
                if(dir === "t"){//顺时针
                    if(qua_st==1&&qua_sp==2||qua_st==1&&qua_sp==3
                        ||qua_st==1&&qua_sp==4||qua_st==2&&qua_sp==3
                        ||qua_st==2&&qua_sp==4||qua_st==3&&qua_sp==4
                        ){
                        angle_lock=true;
                    }else if(qua_st==1&&qua_sp==1
                        ||qua_st==4&&qua_sp==4){
                        if(st_y<sp_y){
                            angle_lock=true;
                        }
                    }else if(qua_st==2&&qua_sp==2
                        ||qua_st==3&&qua_sp==3){
                        if(st_y>sp_y){
                            angle_lock=true;
                        }
                    }
                }else{//逆时针
                    if(qua_st==2&&qua_sp==1||qua_st==3&&qua_sp==1
                    ||qua_st==3&&qua_sp==2||qua_st==4&&qua_sp==1
                    ||qua_st==4&&qua_sp==2||qua_st==4&&qua_sp==3){
                        angle_lock=true;
                    }else if(qua_st==1&&qua_sp==1
                        ||qua_st==4&&qua_sp==4){
                        if(st_y>sp_y){
                            angle_lock=true;
                        }
                    }else if(qua_st==2&&qua_sp==2
                        ||qua_st==3&&qua_sp==3){
                        if(st_y<sp_y){
                            angle_lock=true;
                        }
                    }
                }
                if(angle_lock){
                    if(minAngle<angle_me&&angle_me<maxAngle){
                        status=true;
                    }
                }else{
                    
                    if(minAngle>=angle_me||angle_me>maxAngle){
                        status=true;
                    }
                }
            }
        }
        return status;

        function sountAngle(x,y){
            var angle=0,
                qua=0;
            if(x>0&&y>=0){
                angle=Math.atan(y/x);
                qua=1;
            }else if(x<=0&&y>0){
                x=Math.abs(x);
                angle=Math.atan(x/y)+0.5*Math.PI;
                qua=2;
            }else if(x<0&&y<=0){
                x=Math.abs(x);
                y=Math.abs(y);
                angle=Math.atan(y/x)+Math.PI;
                qua=3;
            }else if(x>=0&&y<0){
                y=Math.abs(y);
                angle=Math.atan(x/y)+1.5*Math.PI;
                qua=4;
            }
            return {
                angle:angle,
                qua:qua,
            };
        
        }
    },

    // 是否在矩形内
    inRect(point,rect){
        let paths = [];
        paths.push({
            x: rect.x + rect.w / 2,
            y: rect.y + rect.h / 2
        });
        paths.push({
            x: rect.x + rect.w / 2,
            y: rect.y - rect.h / 2
        });
        paths.push({
            x: rect.x - rect.w / 2,
            y: rect.y - rect.h / 2
        });
        paths.push({
            x: rect.x - rect.w / 2,
            y: rect.y + rect.h / 2
        });
        if(rotate){
            paths = computedUtil.rotatePoints(paths,{x:rect.x, y:rect.y},rotate);
        }
        return this.inClosedPath(point,paths);
    }
}

const computedUtil = {
    /**
     * 
     * @param {{x:number,y:number}} point 
     * @param {{x:number,y:number}} center 
     * @param {number} rotate 
     * @returns 
     */
    rotatePoint(point,center,rotate){
        if(!rotate){
            return point;
        }
        let angle = rotate * Math.PI / 180;
        return {
            x: (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x,
            y: (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y
        }
    },

    // 将多个点绕中心进行旋转
    /**
     * 
     * @param {Array} points 
     * @param {*} center 
     * @param {*} rotate 
     * @returns 
     */
    rotatePoints(points,center,rotate){
        return points.map(point=>this.rotatePoint(point,center,rotate));
    },

    // 旋转range
    /**
     * 
     * @param {{x:[],y:[]}} range 
     * @param {number} rotate 
     * @param {?{x:number,y:number}} center 
     * @returns 
     */
    rotateRange(range,rotate,center){
        if(!center){
            center = {
                x: (range.x[0] + range.x[1]) / 2,
                y: (range.y[0] + range.y[1]) / 2,
            }
        }
        let points = [
            {x:range.x[1],y:range.y[0]},
            {x:range.x[1],y:range.y[1]},
            {x:range.x[0],y:range.y[0]},
            {x:range.x[0],y:range.y[1]}
        ];

        points = computedUtil.rotatePoints(points,center,rotate);

        var maxX = points[0].x,maxY = points[0].y,minX = points[0].x,minY = points[0].y;
        points.forEach(point=>{
            if(maxX < point.x){
                maxX = point.x;
            }
            if(maxY < point.y){
                maxY = point.y;
            }
            if(minX > point.x){
                minX = point.x;
            }
            if(minY > point.y){
                minY = point.y;
            }
        });
        return {
            x:[minX, maxX],
            y:[minY, maxY]
        };
    },

    // 计算两条线段的交点
    getCrossPoint(lines1,lines2){
        let p1 = {
            x: lines1.startX,
            y: lines1.startY
        }

        let p2 = {
            x: lines1.endX,
            y: lines1.endY
        }

        let q1 = {
            x: lines2.startX,
            y: lines2.startY
        }

        let q2 = {
            x: lines2.endX,
            y: lines2.endY
        }

        if(IsRectCross(p1,p2,q1,q2)){
            if (IsLineSegmentCross(p1,p2,q1,q2)){
                //求交点
                var tmpLeft,tmpRight;
                tmpLeft = (q2.x - q1.x) * (p1.y - p2.y) - (p2.x - p1.x) * (q1.y - q2.y);
                tmpRight = (p1.y - q1.y) * (p2.x - p1.x) * (q2.x - q1.x) + q1.x * (q2.y - q1.y) * (p2.x - p1.x) - p1.x * (p2.y - p1.y) * (q2.x - q1.x);

                x = tmpRight/tmpLeft;

                tmpLeft = (p1.x - p2.x) * (q2.y - q1.y) - (p2.y - p1.y) * (q1.x - q2.x);
                tmpRight = p2.y * (p1.x - p2.x) * (q2.y - q1.y) + (q2.x- p2.x) * (q2.y - q1.y) * (p1.y - p2.y) - q2.y * (q1.x - q2.x) * (p2.y - p1.y); 
                y = tmpRight/tmpLeft;
                return {x,y};
            }
        }
        return false;
        function IsRectCross(p1,p2,q1,q2){
            var ret = Math.min(p1.x,p2.x) <= Math.max(q1.x,q2.x)  &&
                        Math.min(q1.x,q2.x) <= Math.max(p1.x,p2.x) &&
                        Math.min(p1.y,p2.y) <= Math.max(q1.y,q2.y) &&
                        Math.min(q1.y,q2.y) <= Math.max(p1.y,p2.y);
            return ret;
        } 

        function IsLineSegmentCross(pFirst1,pFirst2,pSecond1,pSecond2){
            var line1,line2;
            line1 = pFirst1.x * (pSecond1.y - pFirst2.y) +
                pFirst2.x * (pFirst1.y - pSecond1.y) +
                pSecond1.x * (pFirst2.y - pFirst1.y);
            line2 = pFirst1.x * (pSecond2.y - pFirst2.y) +
                pFirst2.x * (pFirst1.y - pSecond2.y) + 
                pSecond2.x * (pFirst2.y - pFirst1.y);
            if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))
                return false;
            line1 = pSecond1.x * (pFirst1.y - pSecond2.y) +
                pSecond2.x * (pSecond1.y - pFirst1.y) +
                pFirst1.x * (pSecond2.y - pSecond1.y);
            line2 = pSecond1.x * (pFirst2.y - pSecond2.y) + 
                pSecond2.x * (pSecond1.y - pFirst2.y) +
                pFirst2.x * (pSecond2.y - pSecond1.y);
            if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))
                return false;
            return true;
        }
    },

    // 判断两个矩形是否相交，返回相交的矩形位置信息
    getCrossRect(rect1,rect2){
        var flag = true;
        if (rect1.x<=rect2.x && rect1.x+rect1.width<=rect2.x) flag = false;
        if (rect2.x<=rect1.x && rect2.x+rect2.width<=rect1.x) flag = false;
        if (rect1.y<=rect2.y && rect1.y+rect1.height<=rect2.y) flag = false;
        if (rect2.y<=rect1.y && rect2.y+rect2.height<=rect1.y) flag = false;

        if (flag==true){
            let x = Math.max(rect1.x,rect2.x)
            let y = Math.max(rect1.y,rect2.y)
            let width = Math.min(rect1.x+rect1.width,rect2.x+rect2.width)-Math.max(rect1.x,rect2.x)
            let height = Math.min(rect1.y+rect1.height,rect2.y+rect2.height)-Math.max(rect1.y,rect2.y);
            return {x,y,width,height}
        }
        return false;
    },

    // 合并范围
    compareRange(range,toRange){
        if(!toRange){
            return {
                x:[
                    range.x[0],
                    range.x[1]
                ],
                y:[
                    range.y[0],
                    range.y[1]
                ]
            };
        }
        if(!range){
            return {
                x:[
                    toRange.x[0],
                    toRange.x[1]
                ],
                y:[
                    toRange.y[0],
                    toRange.y[1]
                ]
            };
        }
        var compare = {
            x:[0,0],
            y:[0,0]
        }
        compare.x[0] = toRange.x[0] < range.x[0] ? toRange.x[0] : range.x[0];
        compare.x[1] = toRange.x[1] > range.x[1] ? toRange.x[1] : range.x[1];
        compare.y[0] = toRange.y[0] < range.y[0] ? toRange.y[0] : range.y[0];
        compare.y[1] = toRange.y[1] > range.y[1] ? toRange.y[1] : range.y[1];
        return compare;
    }

}

function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function makeMap(str,isLowerCase){
    let map = {};
    let arr = str.split(",");
    arr.forEach(item=>{
        map[item] = true;
    });
    return isLowerCase?(str)=>map[str.toUpperCase()]:(str)=>map[str];
}

// 判断单位是否合法
var checkUnits = makeMap("mm,mils");

// 判断图形层是否合法
var checkLayer = makeMap("st,sb,at,ab,sm_t,sm_b,et,eb,bt,bb,pt,pb");

// 判断pin的图层是否合法
var checkPinLayer = makeMap("b,bs_t,bs_b,bp_t,bp_b,t,ts_t,ts_b,tp_t,tp_b,i,is_t,is_b,ip_t,ip_b,drill");

class DrawEnca{
    /**
     * @type {Encapsulation}
     */
    encaInstance = null;
    /**
     * @type {ActualCanvas}
     */
    actualCanvas = null;

    /**
     * @type {VirtualCanvas}
     */
    virtualCanvas = null;
    
    /**
     * @type {HTMLElement} 绘制的位置
     */
    drawParent = null;

    constructor(encaData){
        this.encaInstance = new Encapsulation(encaData);
        this.actualCanvas = new ActualCanvas();
        this.virtualCanvas = new VirtualCanvas();
        this.actualCanvas.addDraw(this.virtualCanvas);
        this.initEvent();
    }

    setEncaData(encaData){
        this.encaInstance.setEncaData(encaData);
    }

    drawTo(parent){
        this.drawParent = parent;
        this.actualCanvas.appendTo(parent);
        // parent.appendChild(this.virtualCanvas.canvas);
    }

    initEvent(){
        // 滚轮事件
        this.actualCanvas.setEvent("wheel",util.throttle((e)=>{
            Event.trigger("wheel",e);
        },16));

        // mousemove事件
        this.actualCanvas.setEvent("mousemove",util.throttle((e)=>{
            Event.trigger("mousemove",e);
        },16));

        // mousedown事件
        this.actualCanvas.setEvent("mousedown",util.throttle((e)=>{
            Event.trigger("mousedown",e);
        },16));
    }

    draw(){
        this.virtualCanvas.setDrawData(this.encaInstance.trancegramList);
        this.actualCanvas.setScale(0.1);
        this.actualCanvas.draw();
        this.actualCanvas.goCenter();
    }
}

class DrawPCB{
    drawParent = null;

    viewStatus = {
        etch:{},
        noetch:{},
        other:{
            via:true,
            grid:true,
            traces:true,
            electricCopper:true,
            componentName:true
        }
    }

    /**
     * @type {PCB}
     */
    PCBInstance = null;

    /**
     * @type {PCBCanvas}
     */
    PCBCanvas = null;

    constructor(PCBData){
        console.log(PCBData);
        this.PCBInstance = new PCB();
        this.PCBCanvas = new PCBCanvas();
        this.PCBCanvas.setDrawPcb(this);
        this.initEvent();

        if(PCBData){
            this.setPCBData(PCBData);
        }
    }

    // 设置pcb版的数据
    setPCBData(PCBData){
        let handleTime = performance.now();

        this.PCBInstance.setPcbData(PCBData);

        this.PCBInstance.layerDifinition.etch.forEach(layer=>{
            let laverName = layer.name;
            if(laverName == "TOP" || laverName == "BOTTOM"){
                this.viewStatus.etch[laverName] = true;
            }else{
               this.viewStatus.etch[laverName] = false;
            }
        });

        this.PCBInstance.layerDifinition.noetch.forEach(layer=>{
            this.viewStatus.noetch[layer.name] = false;
        });

        console.log("处理pcb版耗时：" + handleTime + "ms");

    }

    // 设置canvas的位置
    drawTo(parent){
        this.drawParent = parent;
        this.PCBCanvas.appendTo(parent);
        this.PCBCanvas._init();
        // parent.appendChild(this.virtualCanvas.canvas);
    }

    // 卸载
    unload(){
        if(this.drawParent){
            this.PCBCanvas.removeTo();
        }
        this.PCBCanvas._unload();
    }

    // 设置缩放倍速
    setScale(scale){
        this.PCBCanvas.setScale(scale);
    }

    getScale(){
        return this.PCBCanvas.getScale();
    }

    // 设置原点的位置
    setOrigin(origin){
        this.PCBCanvas.setOrigin(origin);
    }

    // 获取原点

    getOrigin(){
        return this.PCBCanvas.getOrigin();
    }

    // 切换电气层显示
    changeEtchLayerView(deviceView){
        if(!deviceView){
            deviceView = {
                top:true,
                bottom:true
            }
        }

        // this.PCBInstance.layerDifinition.etch.forEach(layer=>{
        //     this.viewStatus.etch[layer] = false;
        // });

        for(let layer in deviceView){
            this.viewStatus.etch[layer.toUpperCase()] = deviceView[layer] || false;
        }
        // this.goCenter()
        this.draw();
    }

    // 切换非电气层显示
    changeNoetchLayerView(viesStatus){

        // this.PCBInstance.layerDifinition.noetch.forEach(layer=>{
        //     this.viewStatus.noetch[layer.name] = false;
        // });

        for(let layer in viesStatus){
            this.viewStatus.noetch[layer] = viesStatus[layer] || false;
        }
        this.draw();
    }

    // 切换其他显示
    changeOtherView(status){
        for(let attr in this.viewStatus.other){
            if(status[attr] != undefined){
                this.viewStatus.other[attr] = !!status[attr];
            }
        }
        
        this.draw();
    }

    // 绘制图形
    draw(){
        this.PCBCanvas.drawPcb()
    }

    // pcb版居中显示
    goCenter(){
        if(this.PCBInstance.width == 0 && this.PCBInstance.height == 0){
            let origin = {
                x: this.PCBCanvas.canvasCenter.x,
                y: this.PCBCanvas.canvasCenter.y
            }
            this.setScale(this.PCBInstance.units == "mm" ? 0.5 * 39.37 : 0.5);
            this.setOrigin(origin);
            return;
        }
        // 计算缩放比例
        // let wScale = this.PCBCanvas.width / (this.PCBInstance.range.x[1] - this.PCBInstance.range.x[0]);
        // let hScale = this.PCBCanvas.height / (this.PCBInstance.range.y[1] - this.PCBInstance.range.y[0]);

        let wScale = this.PCBCanvas.width / this.PCBInstance.width;
        let hScale = this.PCBCanvas.height / this.PCBInstance.height;

        let scale = wScale > hScale ? hScale : wScale;

        this.setScale(scale);
        
        // 计算原点
        // let origin = {
        //     x: this.PCBCanvas.width / 2 - (this.PCBInstance.range.x[1] + this.PCBInstance.range.x[0]) / 2 * scale,
        //     y: this.PCBCanvas.height /2 + (this.PCBInstance.range.y[1] + this.PCBInstance.range.y[0]) / 2 * scale
        // }
        let origin = {
            x: this.PCBCanvas.width / 2 - this.PCBInstance.width / 2 * scale,
            y: this.PCBCanvas.height /2 + this.PCBInstance.height / 2 * scale
        }
        this.setOrigin(origin);
    }

    // 初始化事件
    initEvent(){
        // 滚轮事件
        this.PCBCanvas.setEvent("wheel",util.throttle((e)=>{
            Event.trigger("wheel",e);
        },32));

        // mousemove事件
        this.PCBCanvas.setEvent("mousemove",util.throttle((e)=>{
            Event.trigger("mousemove",e);
        },16));

        // mousedown事件
        this.PCBCanvas.setEvent("mousedown",util.throttle((e)=>{
            Event.trigger("mousedown",e);
        },16));
    }

    // 获取pcb电气板层信息
    getEtchLayers(){
        let layers = this.PCBInstance.layerDifinition.etch.map(etch=>etch.name);
        return layers;
    }

    // 获取非电气层信息
    getNoetchLayers(){
        let layers = JSON.parse(JSON.stringify(this.PCBInstance.layerDifinition.noetch));
        return layers;
    }

    // 获取pcb数据
    getPcbData(){
        return this.PCBInstance.getPcbData();
    }

    // 自动布局
    autoLayout(autoData){
        this.PCBInstance.autoLayout(autoData);
        this.draw();
    }

    // 修改项目名称
    updateProjectName(projectName){
        this.PCBInstance.projectName = projectName;
    }

    touch(point){
        // 将坐标转换为pcb中的坐标
        let scale = this.getScale();
        let origin = this.getOrigin();
        let pcbCoordinate = {
            x: (point.x - origin.x) / scale,
            y: (point.y - origin.y) / scale
        }
        this.PCBInstance.touch(pcbCoordinate);
        this.draw()
    }
}

class PCB{
    units = "mm";

    // 层定义
    layerDifinition = {
        etch:[],
        noetch:[],
        medium:[]
    };

    /**
     * @type {Encapsulation[]}
     */
    encapsulationList = [];

    // 元器件
    components = {
        allCite:[],
        cite:[],
        define:[]
    }

    // 过孔
    vias = {
        defines:[],
        cites:[]
    }

    // 电气铜皮
    electricCopper = {};
    // 电气走线
    traces = {};

    // 非电气丝印线
    silkScreenLines = {};
    noelectricCopper = {};
    texts = {};

    // 电气铜皮

    //  绘制的canvas
    /**
     * @type {PCBCanvas}
     */
    PCBCanvas = null;

    range = {
        x: [0,0],
        y: [0,0],
        top:{
            x:[0,0],
            y:[0,0]
        },
        bottom:{
            x:[0,0],
            y:[0,0]
        }
    };

    width = 0;
    height = 0;

    // 板层厚度
    thickness = "";

    // pcb项目名称
    projectName = "";

    // 网络定义
    networks = [];

    constructor(pcbData){
        if(pcbData){
            this.setPcbData(pcbData);
        }
    }

    setPcbData(pcbData){

        if(!pcbData){
            return;
        }

        this.units = pcbData.header.units;

        // 统计板层厚度
        let thickness = 0;

        // 获取pcb电气板层信息
        pcbData.LayerDifinition.etchList.forEach(etch=>{
            this.layerDifinition.etch.push({
                name:etch.name,
                info:JSON.parse(JSON.stringify(etch))
            });
            thickness += parseFloat(etch.COPPER.thick.trim());
        });

        // 装配顶层，装配底层，丝印顶层，丝印底层，钢网顶层，钢网底层，阻焊顶层，阻焊底层

        let chineseNameTable = {userASMTop:"装配顶层",userASMBot:"装配底层",userSILKTop:"丝印顶层",userSILKBot:"丝印顶层",userPMASKTop:"钢网顶层",userPMASKBot:"钢网底层",userSMASKTop:"阻焊顶层",userSMASKBot:"阻焊底层"};
        // 获取pcb非电气板层信息
        pcbData.LayerDifinition.NoEtchList.forEach(noetch=>{
            this.layerDifinition.noetch.push({
                chineseName: chineseNameTable[noetch.name],
                name: noetch.name,
                originName: noetch.orgLayer
            });
        });

        // 获取中间层板层信息
        pcbData.LayerDifinition.mediumList.forEach(middle=>{
            this.layerDifinition.medium.push({
                name:middle.name,
                plank: middle.plank,
                thick: middle.thick,
                type: middle.type,
                z_index: middle.z_index
            });
            thickness += parseFloat(middle.thick.trim());
        });

        // 初始化走线和电气铜皮数据
        this.layerDifinition.etch.forEach(etch=>{
            let layer = etch.name;
            this.traces[layer] = [];
            this.electricCopper[layer] = [];
            this.components.cite[layer] = [];
        });

        // 初始化非电气层丝印线,字和铜皮数据
        this.layerDifinition.noetch.forEach(noetch=>{
            this.silkScreenLines[noetch.name] = [];
            this.noelectricCopper[noetch.name] = [];
            this.texts[noetch.name] = [];
        });

        // 获取pcb元器件
        this.components = handlePcbDevices(pcbData, this.components);

        // 获取pcb版大小
        this.width = pcbData.PCBBOX.box.max_x;
        this.height = pcbData.PCBBOX.box.max_y;
        // pcb厚度
        this.thickness = thickness;

        this.projectName = pcbData.header.prjName;

        // 读取走线数据
        pcbData.ElementInstance.Traces.forEach(trace=>{
            let layer = trace.layer;
            if(this.traces[layer]){
                if(trace.data.name.toUpperCase() == "LINE"){
                    this.traces[layer].push(new TLine(this.units,layer,trace.data));
                }else{
                    this.traces[layer].push(new TArc(this.units,layer,trace.data));
                }
            }
        });

        // 读取电气铜皮数据
        pcbData.ElementInstance.coppers.forEach(copper=>{
            let layer = copper.layer;
            if(this.electricCopper[layer]){
                this.electricCopper[layer].push(new CShape(this.units, layer, copper));
            }
        });

        // 获取过孔

        // 处理pad
        // pad原始id与pad对应
        let idToPad = {};

        let defines = [];
        pcbData.ElementInstance.vias.viaDefine.forEach(pad=>{
            let padInstance = new VPad(this.units,pad);
            padInstance.setParent(this);
            idToPad[pad.id] = padInstance;
            defines.push(padInstance);
        });

        this.vias.defines = defines;

        let cites = [];
        pcbData.ElementInstance.vias.viaList.forEach(pin=>{
            let pinInstance = new VPin(this.units,pin);
            pinInstance.setViaDefine(idToPad[pin.choose]);
            pinInstance.setParent(this);
            cites.push(pinInstance);
        });

        this.vias.cites = cites;

        // 获取非电气层数据
        // 获取丝印线
        pcbData.ElementInstance.paths.forEach(path=>{
            this.silkScreenLines[path.layer].push(new PLine(this.units, path.layer, path.data));
        });
        // 获取非电气铜皮
        pcbData.ElementInstance.shapes.forEach(shape=>{
            this.noelectricCopper[shape.layer].push(new PShape(this.units, shape.layer, shape));
        });

        // 获取字
        pcbData.ElementInstance.texts.forEach(text=>{
            this.texts[text.layer].push(new PText(this.units,text.layer,text))
        });

        // 获取网络定义
        this.networks = pcbData.NetsDifinition.map(nets=>{
            return new PcbNetwork(nets);
        });

        // layerList='( ("userASMTop" "BOARD GEOMETRY/ASSEMBLY_TOP") ("userASMBot" "BOARD GEOMETRY/ASSEMBLY_BOTTOM")
        //     ("userSILKTop" "BOARD GEOMETRY/SILKSCREEN_TOP") ("userSILKBot" "BOARD GEOMETRY/SILKSCREEN_BOTTOM")
        //     ("userPMASKTop" "BOARD GEOMETRY/PASTEMASK_TOP" ) ("userPMASKBot" "BOARD GEOMETRY/PASTEMASK_BOTTOM")
        //     ("userSMASKTop" "BOARD GEOMETRY/SOLDERMASK_TOP") ("userSMASKBot" "BOARD GEOMETRY/SOLDERMASK_BOTTOM")
        //   )

        function handlePcbDevices(pcbData,selfDevices){
            let deviceData = {};
            let components = pcbData.DevicesDefinition;

            pcbData.ElementInstance.components.forEach(encaLoca=>{
               
                if(!deviceData[encaLoca.choose]){
        
                    let device = new Device(components.find(dev=>dev.id == encaLoca.choose));
        
                    deviceData[encaLoca.choose] = device;

                    selfDevices.define.push(device);
                }

                let device = deviceData[encaLoca.choose];

                let citeDevice = new CiteDevice(device,encaLoca);

                selfDevices.cite[encaLoca.layer.toUpperCase()].push(citeDevice);

                selfDevices.allCite.push(citeDevice);
            });
            return selfDevices;
        }
    }

    autoLayout(autoList){
        autoList.forEach(addr=>{
            let name = addr[0];
            let x = addr[1],y = addr[2], rotate = addr[3], layer = addr[4];
            this.components.allCite.forEach(citeDevice=>{
                if(citeDevice.name == name){
                    citeDevice.changeCiteInfo({x,y,rotate,layer});
                }
            });
        });

        // 清空
        this.layerDifinition.etch.forEach(etch=>{
            this.components.cite[etch.name] = [];
        });

        this.components.allCite.forEach(citeDevice=>{
            this.components.cite[citeDevice.layer.toUpperCase()].push(citeDevice);
        });
    }

    changePinLink(){
        
    }

    getPcbData(){

        // 引用的元器件
        let DevicesDefinition = [];
        // pcb版元素
        let ElementInstance = {
            Traces: [],
            components: [],
            coppers: [],
            paths: [],
            shapes: [],
            texts: [],
            vias: {
                viaDefine:[],
                viaList:[]
            }
        }
        // 层定义
        let LayerDifinition = {
            etchList:[],
            NoEtchList:[],
            mediumList:[]
        }
        // 网络定义
        let NetsDifinition = [];
        
        // pcb版信息
        let PCBBOX = {
            box:{
                max_x: this.width,
                max_y: this.height,
                min_x: 0,
                min_y: 0
            },
            PCBThickness: this.thickness
        }
        let header = {
            units: this.units,
            prjName: this.projectName
        }

        // 元器件索引
        let deviceIndex = 0;

        let deviceIndexs = {};

        // 遍历电气层
        this.layerDifinition.etch.forEach(etch=>{

            LayerDifinition.etchList.push(JSON.parse(JSON.stringify(etch.info)));
            // 元器件
            this.components.cite[etch.name].forEach(citeData=>{

                let device = citeData.device;
                let choose = 0;

                if(!deviceIndexs[device.id]){
                    deviceIndex++;
                    let rawDevice = device.getRawData();
                    DevicesDefinition.push(rawDevice);
                    deviceIndexs[device.id] = {
                        index: deviceIndex
                    };
                    choose = deviceIndex;
                }else{
                    choose = deviceIndexs[device.id].index;
                }

                let deviceInfo = {
                    box: {
                        x:[citeData.box.x[0], citeData.box.x[1]],
                        y:[citeData.box.y[0], citeData.box.y[1]]
                    },
                    layer: citeData.layer,
                    name: citeData.name,
                    rotate: citeData.rotate,
                    x: citeData.x,
                    y: citeData.y,
                    choose
                }

                ElementInstance.components.push(deviceInfo);
            });
            // 走线
            this.traces[etch.name].forEach(trace=>{
                ElementInstance.Traces.push({
                    data: trace.getRawData(),
                    layer: etch.name
                })
            });
            // 铜皮
            this.electricCopper[etch.name].forEach(copper=>{
                ElementInstance.coppers.push(copper.getRawData());
            });
        });

        // 遍历非电气层
        this.layerDifinition.noetch.forEach(noetch=>{
            LayerDifinition.NoEtchList.push({
                name: noetch.name,
                orgLayer: noetch.originName
            });
            // 丝印线
            this.silkScreenLines[noetch.name].forEach(line=>{
                ElementInstance.paths.push({
                    layer: noetch.name,
                    data: line.getRawData
                });
            });

            // 非电气铜皮
            this.noelectricCopper[noetch.name].forEach(shape=>{
                ElementInstance.shapes.push(shape.getRawData());
            });

            // 字
            this.texts[noetch.name].forEach(text=>{
                ElementInstance.texts.push(text.getRawData());
            });
        });

        // 遍历中间层
        LayerDifinition.mediumList = this.layerDifinition.medium.map(medium=>{
            return {
                name: medium.name,
                plank: medium.plank,
                thick: medium.thick,
                type: medium.type,
                z_index: medium.z_index
            }
        });

        // 获取过孔定义
        ElementInstance.vias.viaDefine = this.vias.defines.map(via=>via.getRawData());

        ElementInstance.vias.viaList = this.vias.cites.map(vpin=>vpin.getRawData());

        // 获取网络定义
        NetsDifinition = this.networks.map(net=>{
            return net.getRawData();
        });

        return {
            ElementInstance,
            LayerDifinition,
            DevicesDefinition,
            NetsDifinition,
            PCBBOX,
            header
        };
    }

    touch(point){
        this.components.allCite.forEach(device=>{
            device.touch(point);
        });
    }
}

// pcb网络定义
class PcbNetwork {
    citeDevices = [];

    name = "";

    prop = {
        DATA_RATE: "",
        DIFF_POLARITY: "NULL",
        GND_ON: "NULL",
        NET_GROUPE: "",
        NET_TYPE: "NULL",
        SIG_FRIQ: "",
        SIG_STANDARD: "NULL",
        VOTAGE_RANGE: ""
    }

    constructor(networkData){
        if(networkData){
            this.setNetworkData(networkData);
        }
    }

    setNetworkData(networkData){
        if(!networkData){
            return;
        }
        let p2p = networkData.P2P;

        Object.keys(p2p).forEach(key=>{
            if(!(p2p[key] instanceof Array)){
                return;
            }
            this.citeDevices[key] = p2p[key].map(value=>value);
        });

        this.name = networkData.name;

        this.prop.DATA_RATE = networkData.prop.DATA_RATE;
        this.prop.DIFF_POLARITY = networkData.prop.DIFF_POLARITY;
        this.prop.GND_ON = networkData.prop.GND_ON;
        this.prop.NET_GROUPE = networkData.prop.NET_GROUPE;
        this.prop.NET_TYPE = networkData.prop.NET_TYPE;
        this.prop.SIG_FRIQ = networkData.prop.SIG_FRIQ;
        this.prop.SIG_STANDARD = networkData.prop.SIG_STANDARD;
        this.prop.VOTAGE_RANGE = networkData.prop.VOTAGE_RANGE;
    }

    getRawData(){
        let networkData = {
            P2P: {},
            name: this.name,
            prop:{}
        }

        Object.keys(this.citeDevices).forEach(key=>{
            networkData.P2P[key] = this.citeDevices[key].map(value=>value);
        });

        networkData.prop.DATA_RATE = this.prop.DATA_RATE;
        networkData.prop.DIFF_POLARITY = this.prop.DIFF_POLARITY;
        networkData.prop.GND_ON = this.prop.GND_ON;
        networkData.prop.NET_GROUPE = this.prop.NET_GROUPE;
        networkData.prop.NET_TYPE = this.prop.NET_TYPE;
        networkData.prop.SIG_FRIQ = this.prop.SIG_FRIQ;
        networkData.prop.SIG_STANDARD = this.prop.SIG_STANDARD;
        networkData.prop.VOTAGE_RANGE = this.prop.VOTAGE_RANGE;

        return networkData;
    }
}

// 引用的元器件
class CiteDevice {
    device = null;

    name = "";

    layer = "top";

    x = 0;
    y = 0;

    rotate = 0;

    box = {
        x:[0,0],
        y:[0,0]
    }

    constructor(device,citeInfo){
        this.setDevice(device);
        this.setCite(citeInfo);
    }

    setDevice(device){
        if(device instanceof Device){
            this.device = device;
        }
    }

    setCite(citeInfo){
        this.name = citeInfo.name;
        this.layer = citeInfo.layer;
        this.x = citeInfo.x;
        this.y = citeInfo.y;
        this.rotate = citeInfo.rotate;
        if(citeInfo.box){
            this.box.x = [citeInfo.box.x[0], citeInfo.box.x[1]];
            this.box.y = [citeInfo.box.y[0], citeInfo.box.y[1]];
        }

    }

    changeCiteInfo(citeInfo){
        this.layer = citeInfo.layer;
        this.x = citeInfo.x;
        this.y = citeInfo.y;
        this.rotate = citeInfo.rotate;
    }

    touch(point){
        let pcbCoordinate = computedUtil.rotatePoint({
            x: point.x - this.x,
            y: point.y - this.y
        },{x: this.x, y: this.y}, -this.rotate);
        this.device.touch(pcbCoordinate);
    }
}

// 元器件定义
class Device{
    id = "";

    name = "";

    /**
     * @type {Encapsulation}
     */
    encapsulation = null;

    type = "";

    pinsList = [];

    signalModel = [];

    constructor(device){
        this.id = uuidv4();
        if(device){
            this.setDeviceData(device);
        }
    }

    setDeviceData(deviceData){
        let enca = deviceData.Footprint.find(en=>en.id == deviceData.choose);
        this.encapsulation = new Encapsulation(enca);
        this.name = deviceData.name;
        this.type = deviceData.type;
        this.pinsList = JSON.parse(JSON.stringify(deviceData.pinsList));
        this.signalModel = JSON.parse(JSON.stringify(deviceData.signalModel));
    }

    getRawData(){
        let encaData = this.encapsulation.getRawData();
        encaData.id = 1;
        return {
            Footprint: [encaData],
            choose: 1,
            name: this.name,
            pinsList: JSON.parse(JSON.stringify(this.pinsList)),
            signalModel: JSON.parse(JSON.stringify(this.signalModel)),
            type: this.type
        }
    }

    touch(point){
        this.encapsulation.touch(point);
    }
}

class Encapsulation{
    encapsulation_name = "";

    deviceInfo = {
        name:"",
        layer:"",
        range:{
            x:[0,0],
            y:[0,0]
        },

        // 封装的位置
        x: 0,
        y: 0,

        // 旋转角度
        rotate:0
    }

    type = "PACKAGE"

    units = "mm";

    _history = [];

    rawData = {};

    // 图形编号集合
    #numberList = [];

    // 图形集合
    /**
     * @type {BaseImage []}
     */
    diagramList = [];

    // Pad集合
    /**
     * @type {EPad []}
     */
    pads = [];

    // 图层集合
    canvasList = [];

    // 显示的canvas
    constructor(encaData){
        if(encaData){
            this.setEncaData(encaData);
        }
    }

    setEncaData(encaData){
        if(getRawType(encaData) !== "Object" || getRawType(encaData.img_data) !== "Object"){
            throw "传入的封装数据有误！";
        }else{
            this.rawData = encaData;

            this.units = encaData.units || "mm";

            try{
                this.transformEncaData(encaData);
            }catch(e){
                console.log(encaData);
            }
    
        }
    }

    transformEncaData(encaData){
        let imgData = encaData.img_data;
        // 将数据进行遍历
        let bigLayerList = ["ss","asm","sm","e","b","p"];
        let layerList = {ss:["st","sb"],asm:["at","ab"],sm:["sm_t","sm_b"],e:["et","eb"],b:["bt","bb"],p:["pt","pb"]};

        // 处理pad

        // pad原始id与pad对应
        let idToPad = {}

        imgData.pads.forEach(pad=>{
            let padInstance = new EPad(this.units,pad);
            padInstance.setEncapsulation(this);
            idToPad[pad.id] = padInstance;
            this.pads.push(padInstance);
        });

        imgData.pins.forEach(pin=>{
            let pinInstance = new EPin(this.units,pin);
            pinInstance.setPad(idToPad[pin.pin_padid]);
            pinInstance.setEncapsulation(this);
            this.diagramList.push(pinInstance);
        });

        bigLayerList.forEach((bigLayer)=>{
            let smallLayerList = layerList[bigLayer];
            if(!imgData[bigLayer]){
                return;
            }
            var bigLayerData = imgData[bigLayer];
            if(!bigLayerData){
                return;
            }
            smallLayerList.forEach((smallLayer)=>{
                var smallLayerData = bigLayerData[smallLayer];
                if(!smallLayerData){
                    return;
                }
                if(getRawType(smallLayerData.texts) === "Array"){
                    smallLayerData.texts.forEach(text=>{
                        let figureInstance = new EText(this.units,smallLayer,text);
                        figureInstance.setEncapsulation(this);
                        this.diagramList.push(figureInstance);
                    });
                }

                if(getRawType(smallLayerData.paths) === "Array"){
                    smallLayerData.paths.forEach(path=>{
                        let figureInstance = EPath.create(path,this.units,smallLayer);
                        figureInstance.setEncapsulation(this);
                        this.diagramList.push(figureInstance);
                    });
                }

                if(getRawType(smallLayerData.shapes) === "Array"){
                    smallLayerData.shapes.forEach(shape=>{
                        let figureInstance = new EShape(this.units,smallLayer,shape);
                        figureInstance.setEncapsulation(this);
                        this.diagramList.push(figureInstance);
                    });
                }
            });
        });
    }

    // 恢复
    redo(){
        
    }

    // 撤销
    undo(){

    }

    // 获取范围
    getRange(){
        let range = null;
        this.diagramList.forEach(img=>{
            var dirRange = img.getRange();
            if(!dirRange){
                throw img
            }
            range = computedUtil.compareRange(range,dirRange);
        });
        if(!range){
            range = {
                x:[0,0],
                y:[0,0]
            }
        }
        return range;
    }

    // 获取原始数据
    getRawData(){
        let smallToBig = {st:"ss",sb:"ss",at:"asm",ab:"asm",sm_t:"sm",sm_b:"sm",et:"e",eb:"e",bt:"b",bb:"b",pt:"p",pb:"p"};
        let bigLayerList = ["ss","asm","sm","e","b","p"];
        let layerList = {ss:["st","sb"],asm:["at","ab"],sm:["sm_t","sm_b"],e:["et","eb"],b:["bt","bb"],p:["pt","pb"]};

        let encaData = {
            img_data:{
                pins:[],
                pads:[]
            },
            units: this.units
        }

        bigLayerList.forEach(bLayer=>{
            encaData.img_data[bLayer] = {};
            layerList[bLayer].forEach(layer=>{
                encaData.img_data[bLayer][layer] = {
                    texts:[],
                    paths:[],
                    shapes:[]
                }
            })
        });

        this.diagramList.forEach(figure=>{
            if(figure.type == "pins"){
                encaData.img_data.pins.push(figure.getRawData());
            }else{
                encaData.img_data[smallToBig[figure.layer]][figure.layer][figure.type].push(figure.getRawData());
            }
        });

        this.pads.forEach(pad=>{
            encaData.img_data.pads.push(pad.getRawData());
        });

        return encaData;
    }

    touch(point){
        this.diagramList.forEach(figure=>{
            figure.touch(point);
        });
    }
}

class BaseImage{
    // 图形在封装中的唯一id
    id = 0;

    type = "base";

    units = "mm";

    /**
     * @type {Encapsulation}
     */
    encapsulation = null;

    // 图形编辑的历史记录
    _editHistory = [];

    constructor(units){
        if(!checkUnits(units)){
            throw "units 不是 mm 或 mils",units,this;
        }
        this.units = units;
        // 生成图形id
        this.id = uuidv4();
    }

    // 转换为原始封装数据
    getRawData(){}

    // 转换为绘图数据
    getDrawData(scale){
    }

    // 获取图形的范围
    /**
     * @returns {{x:[],y:[]}}
    */
    getRange(){

    }

    // 获取图形绘制范围
    /**
     * @returns {{x:[],y:[]}}
     */
    getDrawRange(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        let range = this.getRange();
        if(!range){
            console.log(this);
        }
        range.x[0] *= scale;
        range.x[1] *= scale;
        let maxY = range.y[0] * -scale;
        let minY = range.y[1] * -scale;
        range.y[0] = minY;
        range.y[1] = maxY;
        return range;
    }

    // 获取图形的大小
    getSize(){}

    // 获取图形的正中心点
    /**
     * @returns {{x:number,y:number}}
     */
    getCenter(){}

    // 判断点是否在图形内
    inGraph(point){}

    // 更新图形数据
    update(){}

    // 旋转图形
    setRotate(){}

    // 移动图形
    /**
     * 
     * @param {{x:number,y:number}} offset 
     */
    move(offset){}

    // 切换单位制
    changeUnits(){}

    // 恢复编辑
    redo(){}

    // 撤销编辑
    undo(){}

    // 设置原始数据
    setRawData(data){
        if(getRawType(data) != "Object"){
            throw "TypeError:转换" + this.type + "数据失败，需要传入Object，你传入了",getRawType(arcData);
            return false;
        }
        return true;
    }

    // 设置所属封装
    setEncapsulation(encaInstance){
        this.encapsulation = encaInstance;
    }

    // 图形是否在视图内
    inView(canvasOrigin,scale,width,height,rotate){
        let drawRange = this.getDrawRange(scale);
        if(isNaN(drawRange.x[0])){
            console.error("范围计算有误",this)
        }
        if(rotate){
            // drawRange.x[0] += center.x;
            // drawRange.x[1] += center.x;
            // drawRange.y[0] += center.y;
            // drawRange.y[1] += center.y;
            drawRange = computedUtil.rotateRange(drawRange,rotate,{x:0,y:0});
            // console.log(drawRange)
        }

        // console.log(canvasOrigin)
        // return true;
        var myRect = {
            x: drawRange.x[0] + canvasOrigin.x,
            y: drawRange.y[0] + canvasOrigin.y,
            width: Math.abs(drawRange.x[0] - drawRange.x[1]),
            height: Math.abs(drawRange.y[0] - drawRange.y[1])
        }
        let status = computedUtil.getCrossRect(myRect,{
            x:0,
            y:0,
            width,
            height
        });
        // return true;
        return status;
    }

    // 图形是否被选中
    inSelect(point){
        return false;
    }

    touch(point){
        let range = this.getRange();
        if(point.x > range.x[0] && point.x < range.x[1] && point.y > range.y[0] && point.y < range.y[1]){
            this.isTouch = true;
            return true;
        }
    }

    static rotateRange(range,center,rotate){
        let points = [
            [range.x[1],range.y[0]],
            [range.x[1],range.y[1]],
            [range.x[0],range.y[0]],
            [range.x[0],range.y[1]]
        ];

        points = computedUtil.rotatePoints(points,center,rotate);

        var maxX = points[0][0],maxY = points[0][1],minX = points[0][0],minY = points[0][1];
        points.forEach(point=>{
            if(maxX < point[0]){
                maxX = point[0];
            }
            if(maxY < point[1]){
                maxY = point[1];
            }
            if(minX > point[0]){
                minX = point[0];
            }
            if(minY > point[1]){
                minY = point[1];
            }
        });
        range = {
            x:[minX, maxX],
            y:[minY, maxY]
        }
        return range;
    }
}

class Text extends BaseImage{
    // 文字内容
    content = "";
    // 中心坐标
    x = 0;
    y = 0;
    // 字体宽度
    w = 0;
    // 字体高度
    h = 0;
    // 字号
    fontSize = 10;
    // 旋转角度
    rotateAngle = 0;
    // 字体类型
    form = "TEXT";

    constructor(units,data){
        super(units);
        this.type = "texts";
        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.x = data.x || 0;
        this.y = data.y || 0;
        this.content = data.content || "";
        this.rotateAngle = data.rotate || 0;
        this.fontSize = data.textblock;
        // 计算字体大小
        let textSize = this.getSize();
        this.w = textSize.w;
        this.h = textSize.h;
    }

    rotate(rotate,center){
        if(!center){
            this.rotateAngle = rotate;
        }else{
            var rotatePoint = computedUtil.rotatePoint({x:this.x, y:this.y},center,rotate);
            this.x = rotatePoint.x;
            this.y = rotatePoint.y;
            this.rotateAngle += rotate;
        }
    }

    getRawData(){
        return {
            rotate: this.rotateAngle,
            name: this.form,
            x: this.x,
            y: this.y,
            textheight: this.w,
            textwidth: this.h,
            content: this.content,
            textblock: this.fontSize
        }
    }

    getDrawData(scale){
        return {
            id: this.id,
            layer: this.layer,
            type: this.type,
            form: this.form,
            fillStyle:this.fillStyle,
            alpha:this.alpha,
            data: {
                rotate: this.rotateAngle,
                name: this.form,
                x: this.x * scale,
                y: - this.y * scale,
                textheight: this.w * scale,
                textwidth: this.h * scale,
                content: this.content,
                textblock: this.fontSize * scale
            }
        }
    }

    getRange(){
        return {
            x:[this.x - this.w / 2, this.x + this.w / 2],
            y:[this.y - this.h / 2, this.y + this.h / 2]
        }
    }

    getSize(){
        return {
            w: this.content.length * this.fontSize / 2,
            h: this.fontSize
        }
    }
}

class EText extends Text{ 
    layer = "st";

    fillStyle = "";

    constructor(units,layer,data){
        super(units);
        this.setLayer(layer);
        this.fillStyle = styleConfig.layer[this.layer].color_text;
        this.type = "texts";
        if(data){
            this.setRawData(data);
        }
    }
    
    setLayer(layer){
        if(!checkLayer(layer)){
            throw "传入的层有误！"
        }
        this.layer = layer;
    }
}

class PText extends Text{
    layer = "";

    constructor(units,layer,data){
        super(units);
        this.layer = layer;
        if(data){
            this.setRawData(data);
        }
    }
}

class EPath extends BaseImage{
    constructor(){
        this.type = "path";
    }

    static create(lineData,units,layer){
        if(getRawType(lineData) !== "Object"){
            throw "路径数据有误" + lineData;
        }
        if(getRawType(lineData.name) !== "String"){
            throw "路径数据的name有误!" + lineData;
        }
        let form = lineData.name.toUpperCase();
        if(form === "LINE"){
            return new ELine(units,layer,lineData);
        }
        if(form === "ARC"){
            return new EArc(units,layer,lineData);
        }
    }
}

class BasePath extends BaseImage{

    /**
     * @type {BaseImage []}
     */
    path = [];

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        if(!(data instanceof Array)){
            throw "TypeError: 需要一个数组!";
        }
        data.forEach(lineData=>{
            this.path.push(BasePath.create(lineData,this.units));
        });
    }

    getRawData(){
        let paths = [];
        this.path.forEach(line=>{
            paths.push(line.getRawData());
        });
        return {path:paths,form:"PATH"};
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        let draw = [];
        this.path.forEach(base=>{
            draw.push(base.getDrawData(scale));
        });
        return draw;
    }

    getRange(){
        var range = null;

        this.path.forEach(line=>{
            let lineRange = line.getRange();
            range = compareRange(range,lineRange);
        });

        return range;

        function compareRange(range,toRange){
            if(!toRange){
                return {
                    x:[
                        range.x[0],
                        range.x[1]
                    ],
                    y:[
                        range.y[0],
                        range.y[1]
                    ]
                };
            }
            if(!range){
                return {
                    x:[
                        toRange.x[0],
                        toRange.x[1]
                    ],
                    y:[
                        toRange.y[0],
                        toRange.y[1]
                    ]
                };
            }
            var compare = {
                x:[0,0],
                y:[0,0]
            }
            compare.x[0] = toRange.x[0] < range.x[0] ? toRange.x[0] : range.x[0];
            compare.x[1] = toRange.x[1] > range.x[1] ? toRange.x[1] : range.x[1];
            compare.y[0] = toRange.y[0] < range.y[0] ? toRange.y[0] : range.y[0];
            compare.y[1] = toRange.y[1] > range.y[1] ? toRange.y[1] : range.y[1];
            return compare;
        }
    }

    static create(lineData,units){
        if(getRawType(lineData) !== "Object"){
            throw "路径数据有误" + lineData;
        }
        if(getRawType(lineData.name) !== "String"){
            throw "路径数据的name有误!" + lineData;
        }
        let form = lineData.name.toUpperCase();
        if(form === "LINE"){
            return new BaseLine(units,lineData);
        }
        if(form === "ARC"){
            return new BaseArc(units,lineData);
        }
    }
}

class BaseLine extends BaseImage{
    startX = 0;
    startY = 0;
    endX = 0;
    endY = 0;
    constructor(units,lineData){
        super(units);

        this.type = "paths";
        this.form = "LINE";
        if(lineData){
            this.setRawData(lineData);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.startX = data.st_x || 0;
        this.startY = data.st_y || 0;
        this.endX = data.sp_x || 0;
        this.endY = data.sp_y || 0;
    }

    getRawData(){
        return {
            st_x: this.startX,
            st_y: this.startY,
            sp_x: this.endX,
            sp_y: this.endY,
            name: this.form
        }
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }

        return {
            st_x: this.startX * scale,
            st_y: this.startY * - scale,
            sp_x: this.endX * scale,
            sp_y: this.endY * - scale,
            name: this.form
        }
    }

    getRange(){
        var maxX = this.startX > this.endX ? this.startX : this.endX,
            minX = this.startX > this.endX ? this.endX : this.startX,
            maxY = this.startY > this.endY ? this.startY : this.endY,
            minY = this.startY > this.endY ? this.endY : this.startY;

        return {
            x: [minX, maxX],
            y: [minY, maxY]
        }
    }

    rotate(rotate,center){
        if(!center){
            center = {
                x: (this.startX + this.endX) / 2,
                y: (this.startY + this.endY) / 2
            }
        }
        let start = computedUtil.rotatePoint({
            x: this.startX,
            y: this.startY
        },center,rotate);

        let end = computedUtil.rotatePoint({
            x: this.endX,
            y: this.endY
        },center,rotate);

        this.startX = start.x;
        this.startY = start.y;
        this.endX = end.x;
        this.endY = end.y;
    }

    getCenter(){
        return {
            x : (this.startX + this.endX) / 2,
            y : (this.startY + this.endY) / 2
        }
    }

    move(offset){
        this.startX += offset.x;
        this.startY += offset.y;
        this.endX += offset.x;
        this.endY += offset.y;
    }

    static create(lineData,units){
        let baseLine = new BaseLine(units);
        if(getRawType(lineData) != "Object"){
            console.error("TypeError:转换" + baseLine.type + "数据失败，需要传入Object，你传入了" + getRawType(lineData));
            return baseLine;
        }
        baseLine.startX = lineData.st_x || 0;
        baseLine.startY = lineData.st_y || 0;
        baseLine.endX = lineData.sp_x || 0;
        baseLine.endY = lineData.sp_y || 0;
        return baseLine;
    }
}

class BaseArc extends BaseImage{
    // 起始点
    startX = 0;
    startY = 0;
    // 终点
    endX = 0;
    endY = 0;
    // 圆心
    cenX = 0;
    cenY = 0;
    // 方向，true为顺时针，false为逆时针
    direction = true;
    // 半径
    r = 0;

    form = "ARC";

    type = "paths";

    constructor(units,arcData){
        super(units);

        if(arcData){
            this.setRawData(arcData);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.startX = data.st_x || 0;
        this.startY = data.st_y || 0;
        this.endX = data.sp_x || 0;
        this.endY = data.sp_y || 0;
        this.cenX = data.o_x || 0;
        this.cenY = data.o_y || 0;
        this.direction = data.arc_r == "nil";
        this.r = data.r;
    }

    getRawData(){
        return {
            st_x: this.startX,
            st_y: this.startY,
            sp_x: this.endX,
            sp_y: this.endY,
            width: this.lineWidth,
            name: this.form,
            o_x: this.cenX,
            o_y: this.cenY,
            arc_r: this.direction ? "t" : "nil",
            r: this.r
        }
    }
    
    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        
        return {
            st_x: this.startX * scale,
            st_y: -this.startY * scale,
            sp_x: this.endX * scale,
            sp_y: -this.endY * scale,
            width: this.lineWidth * scale,
            name: this.form,
            o_x: this.cenX * scale,
            o_y: -this.cenY * scale,
            arc_r: this.direction,
            r: this.r * scale
        }
    }

    getRange(){
        if(this.endX == this.startX && this.endY == this.startY){
            return {
                x:[this.cenX - this.r, this.cenX + this.r],
                y:[this.cenY - this.r, this.cenY + this.r]
            }
        }
        let isRound = false;
        let maxX = 0,minX = 0,minY = 0,maxY = 0;
        if(this.startX > this.endX){
            maxX = this.startX;
            minX = this.endX;
            if(this.direction == "t"){
                maxY = -(-this.cenY + this.r);
                minY = this.startY;
                if(-this.startY > -this.endY){
                    minY = this.endY;
                    minX = this.cenX - this.r;
                }
                else if(-this.startY < -this.endY){
                    minY = this.startY;
                    maxX = this.cenX + this.r;
                }
            }else{
                maxY = this.startY;
                minY = -(-this.cenY - this.r);
                if(-this.startY > -this.endY){
                    maxY = this.startY;
                    maxX = this.cenX + this.r;
                }
                else if(-this.startY < -this.endY){
                    maxY = this.endY;
                    minX = this.cenX - this.r;
                }
            }
        }
        else if(this.startX < this.endX){
            maxX = this.endX;
            minX = this.startX;
            if(this.direction == "t"){
                minY = -(-this.cenY - this.r);
                maxY = this.startY;
                if(-this.startY < -this.endY){
                    maxY = this.endY;
                    maxX = this.cenX + this.r;
                }
                else if(-this.startY > -this.endY){
                    maxY = this.startY;
                    minX = this.cenX - this.r;
                }
            }else{
                maxY = -(-this.cenY + this.r);
                minY = this.startY;
                if(-this.startY > -this.endY){
                    minY = this.endY;
                    maxX = this.cenX + this.r;
                }
                else if(-this.startY < -this.endY){
                    minY = this.startY;
                    minX = this.cenX - this.r;
                }
            }
        }
        else{
            if(this.startY != this.endY){
                if(this.direction == "t"){
                    if(-this.startY < -this.endY){
                        maxY = this.endY;
                        minY = this.startY;
                        maxX = this.cenX + this.r;
                        minX = this.cenX;
                    }
                    else if(-this.startY > -this.endY){
                        maxY = this.startY;
                        minY = this.endY;
                        maxX = this.cenX;
                        minX = this.cenX - this.r;
                    }
                }else{
                    if(-this.startY > -this.endY){
                        maxY = this.startY;
                        minY = this.endY;
                        maxX = this.cenX + this.r;
                        minX = this.cenX;
                    }
                    else if(-this.startY < -this.endY){
                        maxY = this.endY;
                        minY = this.startY;
                        maxX = this.cenX;
                        minX = this.cenX - this.r;
                    }
                }
            }
            else{
                isRound = true;
                maxY = this.cenY + this.r;
                minY = this.cenY - this.r;
                maxX = this.cenX + this.r;
                minX = this.cenX - this.r;
            }
        }
        if(isRound){
            return {
                x:[minX,maxX],
                y:[minY,maxY]
            };
        }else{
            return {
                x:[minX,maxX],
                y:[maxY,minY]
            };
        }
    }

    getCenter(){
        return {
            x : (this.startX + this.endX) / 2,
            y : (this.startY + this.endY) / 2
        }
    }

    rotate(rotate,center){
        var updateCenter = true;
        if(!center){
            updateCenter = false;
            center = {
                x: this.cenX,
                y: this.cenY
            }
        }
        var start = computedUtil.rotatePoint({
            x: this.startX,
            y: this.startY
        },center,rotate);

        var end = computedUtil.rotatePoint({
            x: this.endX,
            y: this.endY
        },center,rotate);

        if(updateCenter){
            var cen = computedUtil.rotatePoint({
                x: this.cenX,
                y: this.cenY
            },center,rotate);
            this.cenX = cen.x;
            this.cenY = cen.y;
        }

        this.startX = start.x;
        this.startY = start.y;
        this.endX = end.x;
        this.endY = end.y;
    }

    move(offset){
        this.startX += offset.x;
        this.startY += offset.y;
        this.endX += offset.x;
        this.endY += offset.y;
        this.cenX += offset.x;
        this.cenY += offset.y;
    }
}

class BaseRect extends BaseImage{
    width = 0;

    height = 0;

    x = 0;

    y = 0;

    rotate = 0;

    constructor(units,rectData){
        super(units);
        if(rectData){
            this.setRawData(rectData);
        }
    }

    setRawData(data){
        this.width = data.w || 0;
        this.height = data.h || 0;
        this.x = data.x || 0;
        this.y = data.y || 0;
        // this.lineWidth = data.width;
    }

    getRawData(){
        return {
            w: this.width,
            h: this.height,
            x: this.x,
            y: this.y,
            rotate: this.rotate,
            form: "S"
        }
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        return {
            w: Math.round(this.width * scale),
            h: Math.round(this.height * scale),
            x: Math.round(this.x * scale),
            y: Math.round(this.y * - scale),
            rotate: this.rotate,
            form: "S"
            // width: this.lineWidth * scale
        }
    }

    getRange(){
        let range = {
            x: [this.x - this.width / 2, this.x + this.width / 2],
            y: [this.y - this.height / 2, this.y + this.height / 2]
        }

        if(this.rotate){
            range = BaseImage.rotateRange(range,{x: this.x, y: this.y}, this.rotate);
        }

        return range;
    }
}

class BaseCircle extends BaseImage{
    r = 0;

    x = 0;
    
    y = 0;

    type = "C";

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.r = data.r || data.w / 2;
        this.x = data.x || 0;
        this.y = data.y || 0;
    }

    getRawData(){
        return {
            w: this.r * 2,
            h: this.r * 2,
            x: this.x,
            y: this.y,
            r: this.r,
            form: "C"
        }
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        return {
            x: Math.round(this.x * scale),
            y: Math.round(this.y * -scale),
            w: Math.round(this.r * 2 * scale),
            h: Math.round(this.r * 2 * scale),
            r: Math.round(this.r * scale),
            form: "C"
        }
    }

    getRange(){
        return {
            x: [this.x - this.r, this.x + this.r],
            y: [this.y - this.r, this.y + this.r]
        }
    }
}

class BaseOval extends BaseRect{
     constructor(units,data){
         super(units,data);
     }

     getRawData(){
         let rawData = super.getRawData();
         rawData.form = "OV";
         return rawData;
     }

     getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
         let draw = super.getDrawData(scale);
         draw.form = "OV";
         return draw;
     }
}

class BasePolygon extends BaseImage{
    x = 0;

    y = 0;

    r = 0;

    // 多边形的边数
    num = 0;

    rotate = 0;
    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    getRawData(){
        return {
            form: "POLY",
            x: this.x,
            y: this.y,
            r: this.r,
            num: this.num,
            rotate: this.rotate
        }
    }

    setRawData(data){
        if(!super.setRawData(data)) return;
        this.x = data.x || 0;
        this.y = data.y || 0;

        this.r = data.r || 0;
        this.num = data.num || 0;
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }

        return {
            x: Math.round(this.x * scale),
            y: Math.round(this.y * - scale),
            form: "POLY",
            r: Math.round(this.r * scale),
            num: this.num,
            rotate: this.rotate
        }
    }

    getRange(){
        let range = {
            x: [this.x - this.r, this.x + this.r],
            y: [this.y = this.r, this.y + this.r]
        }
        return range;
    }
}

class BaseOctagon extends BasePolygon{
    constructor(units,data){
        data.num = 8;
        super(units,data);
    }

    setRawData(data){
        data.num = 8;
        super.setRawData(data);
    }

    getRawData(){
        return {
            x: this.x,
            y: this.y,
            rotate: this.rotate,
            form: "OC",
            r: this.r
        }
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        return {
            x: Math.round(this.x * scale),
            y: Math.round(this.y * - scale),
            form: "OC",
            r: Math.round(this.r * scale),
            rotate: this.rotate
        }
    }
}

class BaseRoundRect extends BaseRect{

    // 圆角弧度
    r = 0;

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.r = data.r;
    }

    getRawData(){
        let rawData = super.getDrawData(scale);
        rawData.form = "CS";
        rawData.r = this.r;

        return figureUtil.cs2Path(rawData);
    }

    /**
     * 
     * @param {number} scale 
     * @returns {{
     *  w: number;
     *  h: number;
     *  x: number;
     *  y: number;
     *  form: string;
     *  r: number
     * }}
     */
    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        let draw = super.getDrawData(scale);
        draw.form = "CS";
        draw.r = Math.round(this.r * scale);
        return draw;
    }
}

// 带宽度线条
class Line extends BaseLine{
    // 线宽
    lineWidth = 0;

    strokeStyle = "";

    constructor(units,data){
        super(units);

        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.lineWidth = data.width || (this.units == "mm" ? 0.127 : 0.127 * 39.37);
    }

    getRawData(){
        let originData = super.getRawData();
        originData.width = this.lineWidth;
        return originData;
    }

    getRange(){
        var big = {
            a:Math.abs(this.startY - this.endY),
            b:Math.abs(this.startX - this.endX)
        }

        big.c = Math.sqrt(big.a*big.a+big.b*big.b);

        var small = {
            a:(this.lineWidth/2)/big.c * big.a,
            b:(this.lineWidth/2)/big.c * big.b
        }
        var maxX = this.startX + small.a > this.endX + small.a ? this.startX + small.a : this.endX + small.a;
        
        var minX = this.startX - small.a < this.endX - small.a ? this.startX - small.a : this.endX - small.a;
        var maxY = this.startY + small.b > this.endY + small.b ? this.startY + small.b : this.endY + small.b;
        var minY = this.startY - small.b < this.endY - small.b ? this.startY - small.b : this.endY - small.b;

        return {
            x: [minX,maxX],
            y: [minY, maxY]
        }
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        if(this.lineWidth * scale < 0.2){
            // console.log("线宽小于3")
            return [];
        }
        let drawData = super.getDrawData(scale);
        drawData.width = this.lineWidth * scale;
        return {
            id:this.id,
            layer: this.layer,
            type: this.type,
            form: this.form,
            strokeStyle:this.strokeStyle,
            data:drawData
        }
    }

    inSelect(point){

    }
}

// 封装线条
class ELine extends Line{
    layer = "st";

    constructor(units,layer,data){
        super(units,data);
        this.setLayer(layer);
    }

    setLayer(layer){
        if(!checkLayer(layer)){
            throw "传入的参数有误！"
        }
        this.layer = layer;
        this.strokeStyle = styleConfig.layer[this.layer].path.color_line;
    }
}

// pcb丝印线条
class PLine extends Line{
    layer = "";
    strokeStyle = "green";
    constructor(units,layer,data){
        super(units,data);
        this.setLayer(layer);
    }

    setLayer(layer){
        if(!layer){
            throw "传入的layer有误！";
        }
        this.layer = layer;
    }
}

class TLine extends ELine{
    constructor(units,layer,data){
        super(units,layer,data);
        // this.layer = layer;
    }

    setLayer(layer){
        this.layer = layer;
    }
}

class EArc extends BaseArc{
    layer = "st";
    // 线宽
    lineWidth = 0;

    strokeStyle = "";

    constructor(units,layer,data){
        super(units);
        this.setLayer(layer);
        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.lineWidth = data.width || 0;
    }

    setLayer(layer){
        if(!checkLayer(layer)){
            throw "传入的参数有误！"
        }
        this.layer = layer;
        
        this.strokeStyle = styleConfig.layer[this.layer].path.color_line;
    }

    getRawData(){
        let originData = super.getRawData();
        originData.width = this.lineWidth;
        return originData;
    }

    getRange(){
        var range = super.getRange();
        range.x[0] -= this.lineWidth/2;
        range.x[1] += this.lineWidth/2;
        range.y[0] -= this.lineWidth/2;
        range.y[1] += this.lineWidth/2;
        return range;
    }

    getDrawData(scale){
        let drawData = super.getDrawData(scale);
        drawData.width = this.lineWidth * scale;
        return {
            id:this.id,
            layer: this.layer,
            type: this.type,
            form: this.form,
            strokeStyle: this.strokeStyle,
            data:drawData
        }
    }

    getCenter(){
        return {
            x : (range.x[0] + range.x[1]) / 2,
            y : (range.y[0] + range.y[1]) / 2
        }
    }
}

class TArc extends EArc{
    constructor(units,layer,data){
        super(units,layer,data);
    }

    setLayer(layer){
        this.layer = layer;
    }
}

class Shape extends BaseImage{
    layer = "st";

    /**
     * @type {BaseLine []}
     */
    outline = [];

    /**
     * @type {BaseLine [][]}
     */
    fill = [];

    type = "shapes";

    fillStyle = "blue";

    constructor(units,layer,shapeData){
        super(units);
        this.layer = layer;
        if(shapeData){
            this.setRawData(shapeData);
        }
    }

    setRawData(shapeData){
        if(!shapeData){
            return;
        }
        let fill = [],outline = [];
        if(shapeData instanceof Array){
            outline = shapeData;
        }else{
            try {
                
                if(shapeData.fill.length &&typeof shapeData.fill.forEach == "function"){
                    fill = shapeData.fill;
                }
            } catch (error) {
                console.log(shapeData);
            }
            if(shapeData.outline.length &&typeof shapeData.outline.forEach == "function"){
                outline = shapeData.outline;
            }
        }

        outline.forEach((pathData)=>{
            this.outline.push(BasePath.create(pathData,this.units));
        });

        fill.forEach((pathData,index)=>{
            if(pathData instanceof Array){
                this.fill[index] = [];
                pathData.forEach(line=>{
                    this.fill[index].push(BasePath.create(line,this.units));
                });
            }else{
                this.fill[0].push(BasePath.create(pathData,this.units))
            }
        });
    }

    getRawData(){
        let shape = {
            outline:[],
            fill:[]
        }
        this.outline.forEach(line=>{
            shape.outline.push(line.getRawData());
        });

        this.fill.forEach((paths,index)=>{
            shape.fill[index] = [];
            paths.forEach(line=>{
                shape.fill[index].push(line.getRawData());
            });
        });

        return shape;
    }

    getDrawData(scale){
        let range = this.getDrawRange(scale);
        if(Math.abs(range.x[0] - range.x[1]) < 1 || Math.abs(range.y[0] - range.y[1]) < 1){
            return [];
        }
        let drawOutline = [],drawFill = [];
        this.outline.forEach(line=>{
            drawOutline.push(line.getDrawData(scale));
        });
        this.fill.forEach((fillItem,index)=>{
            drawFill[index] = [];
            fillItem.forEach(line=>{
                drawFill[index].push(line.getDrawData(scale))
            });
        });
        return {
            id:this.id,
            layer:this.layer,
            type: this.type,
            fillStyle: this.isTouch ? "orange" : this.fillStyle,
            alpha: 0.4,
            data:{
                outline:drawOutline,
                fill:drawFill
            }
        }
    }

    getRange(){

        var outlineRange = null;
        var fillRange = null;

        this.outline.forEach(line=>{
            let lineRange = line.getRange();
            outlineRange = compareRange(outlineRange,lineRange);
        });

        this.fill.forEach(fillItem=>{
            fillItem.forEach(line=>{
                let lineRange = line.getRange();
                fillRange = compareRange(outlineRange,lineRange);
            })
        });

        if(!outlineRange && !fillRange){
            return null;
        }

        return compareRange(outlineRange,fillRange);

        function compareRange(range,toRange){
            if(!toRange){
                return {
                    x:[
                        range.x[0],
                        range.x[1]
                    ],
                    y:[
                        range.y[0],
                        range.y[1]
                    ]
                };
            }
            if(!range){
                return {
                    x:[
                        toRange.x[0],
                        toRange.x[1]
                    ],
                    y:[
                        toRange.y[0],
                        toRange.y[1]
                    ]
                };
            }
            var compare = {
                x:[0,0],
                y:[0,0]
            }
            compare.x[0] = toRange.x[0] < range.x[0] ? toRange.x[0] : range.x[0];
            compare.x[1] = toRange.x[1] > range.x[1] ? toRange.x[1] : range.x[1];
            compare.y[0] = toRange.y[0] < range.y[0] ? toRange.y[0] : range.y[0];
            compare.y[1] = toRange.y[1] > range.y[1] ? toRange.y[1] : range.y[1];
            return compare;
        }
    }

    getCenter(){
        var xSum = 0, ySum = 0;
        this.outline.forEach(line=>{
            let center = line.getCenter();
            xSum += center.x;
            ySum += center.y;
        });
        return {
            x: xSum / this.outline.length,
            y: ySum / this.outline.length
        }
    }
}

class EShape extends Shape{
    constructor(units,layer,shapeData){
        if(!checkLayer(layer)){
            throw "传入的参数有误！"
        }
        super(units,layer,shapeData);
        
        this.fillStyle = styleConfig.layer[this.layer].shape.color_fill;
    }
}

class CShape extends Shape{

    networkName = "";

    constructor(units,layer,shapeData){
        super(units,layer);
        if(shapeData){
            this.setRawData(shapeData);
        }
    }

    setRawData(shapeData){
        super.setRawData(shapeData);
        this.networkName = shapeData.netName;
    }

    getRawData(){
        let rawData = super.getRawData();
        rawData.netName = this.networkName;
        rawData.layer = this.layer;
        return rawData;
    }
}

class PShape extends Shape{
    constructor(units,layer,shapeData){
        super(units,layer);
        if(shapeData){
            this.setRawData(shapeData);
        }
    }

    getRawData(){
        let rawData = super.getRawData();
        rawData.layer = this.layer;
        return rawData;
    }
}

class Pin extends BaseImage{
    /**
     * @type {EPad}
     */
    pad = null;

    x = 0;

    y = 0;

    rotate = 0;

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.x = data.x;
        this.y = data.y;
        this.rotate = data.rotate;
    }

    setPad(pad){
        if(!(pad instanceof EPad)){
            throw "TypeError: 传入的Pad数据有误，需要一个EPad实例！";
        }
        this.pad = pad;
    }

    getRawData(){
        return {
            x: this.x,
            y: this.y,
            rotate: this.rotate
        }
    }

    getRange(){
        let padRange = this.pad.getRange();

        if(padRange.x[0] == padRange.x[1]){
            console.error("pad计算有误",this.pad,padRange)
        }

        padRange.x[0] += this.x;
        padRange.x[1] += this.x;
        padRange.y[0] += this.y;
        padRange.y[1] += this.y;

        if(this.rotate){
            padRange = computedUtil.rotateRange(padRange,this.rotate,{x:this.x,y:this.y});
        }

        return padRange;
    }

    getDrawData(scale){
        if(!scale && scale !== 0){
            scale = 1;
        }
        
        //判断是否太小了
        let range = this.getDrawRange(scale);
        let w = (range.x[1] - range.x[0]) / 2;
        let h = (range.y[1] - range.y[0]) / 2;
        if(w <=1 || h <= 1){
            return [];
        }
        if(w <= 2.5 || h <= 2.5){
            let data = {};
            if(w > h){
                let cenY = (range.y[0] + range.y[1]) / 2;
                data = {
                    st_x: Math.round(range.x[0]),
                    sp_x: Math.round(range.x[1]),
                    st_y: Math.round(cenY),
                    sp_y: Math.round(cenY),
                    form:"LINE",
                    width: Math.round(h)
                };
            }else{
                let cenX = (range.x[0] + range.x[1]) / 2;
                data = {
                    st_x: Math.round(cenX),
                    sp_x: Math.round(cenX),
                    st_y: Math.round(range.y[0]),
                    sp_y: Math.round(range.y[1]),
                    form:"LINE",
                    width: Math.round(w)
                };
            }

            return {
                id:this.id,
                // layer: this.layer,
                type: "paths",
                form: "LINE",
                strokeStyle:"red",
                data
            }
        }
        let x = this.x * scale, y = this.y * - scale, rotate = this.rotate, num = this.number;
        let drawPads = this.pad.getDrawData(scale);
        let draw = [];

        drawPads.forEach(drawPad=>{
            drawPad.data.x = x;
            drawPad.data.y = y;
            drawPad.data.pRotate = rotate;
            drawPad.pin_num = num;
            drawPad.type = "pins";
            drawPad.id = this.id;
            draw.push(drawPad);
        });
        return draw;
    }
}

// 引脚
class EPin extends Pin{

    number = "";

    type = "pins";

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    getRawData(){
        return {
            x: this.x,
            y: this.y,
            rotate: this.rotate,
            pin_id: this.number,
            pin_padid: this.pad.id
        }
    }

    setRawData(data){
        super.setRawData(data);
        this.number = data.pin_id;
    }
}

class EPad extends BaseImage{
    type = "pad";

    data = {
        b: null,
        bs_t: null,
        bs_b: null,
        bp_t: null,
        bp_b: null,
        t: null,
        ts_t: null,
        ts_b: null,
        tp_t: null,
        tp_b: null,
        i: null,
        is_t: null,
        is_b: null,
        ip_t: null,
        ip_b: null,
        drill: []
    }

    kind = "smt"

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    getRawData(){
        let padOutLayer = ["b","t","i"];
        let padInLayers = {
            b:["b","bs_t","bs_b","bp_t","bp_b"],
            t:["t","ts_t","ts_b","tp_t","tp_b"],
            i:["i","is_t","is_b","ip_t","ip_b"]
        };
        let layerFormTrans = {C:"CIRCLE",S:"RECTANGLE",OC:"OCTAGON",OV:"OBLONG"};
        let drillFormTrans = {C:"CIRCLE_DRILL",S:"RECTANGLE_SLOT",OC:"OCTAGON_DRILL",OV:"OVAL_SLOT"};

        let pad = {
            id: this.id,
            kind: this.kind,
            drill:[]
        };

        padOutLayer.forEach(oLayer=>{
            pad[oLayer] = {};
            padInLayers[oLayer].forEach(mLayer=>{
                if(this.data[mLayer]){
                    let layerData = this.data[mLayer].figure.getRawData();
                    layerData.skewing_x = this.data[mLayer].offset.x;
                    layerData.skewing_y = this.data[mLayer].offset.y;
                    layerData.rotate = this.data[mLayer].rotate;
                    layerData.form = layerFormTrans[layerData.form] || layerData.form;
                    pad[oLayer][mLayer] = layerData;
                }else{
                    pad[oLayer][mLayer] = {};
                }
            });
        });

        this.data.drill.forEach(drillIns=>{
            let drill = drillIns.figure.getRawData();
                drill.skewing_x = drillIns.offset.x;
                drill.skewing_y = drillIns.offset.y;
                drill.rotate = drillIns.rotate;

            let originDrill = {
                hole: {
                    rotate: drill.rotate,
                    form: drillFormTrans[drill.form] || drill.form,
                    w: drill.w,
                    h: drill.h
                },
                keepout: "nil",
                figure: {
                    w: drill.w,
                    name: "CROSS",
                    h: drill.h
                },
                diameter: drill.w,
                offset: {
                    x: drill.skewing_x,
                    y: drill.skewing_y
                },
                plate: "nil",
                tolerance: {
                    x: 0,
                    y: 0
                },
                uvia: "nil",
                start_end_layer: {
                    end_layer: "ETCH/BOTTOM",
                    st_layer: "ETCH/TOP"
                }
            }
            if(drill.form == "C"){
                originDrill.figure.name = "Null";
            }else if(drill.form == "OV"){
                originDrill.figure.name = "OblongX";
            }else if(drill.form == "S"){
                originDrill.figure.name = "Rectangle";
            }
            pad.drill.push(originDrill);
        });
        return pad;
    }

    setRawData(data){
        super.setRawData(data);

        this.kind = data.kind;

        let self = this;

        let padBigLayer = ["b","t","i","drill"];
        let padSmallLayer = {b:["b","bs_t","bs_b","bp_t","bp_b"],t:["t","ts_t","ts_b","tp_t","tp_b"],i:["i","is_t","is_b","ip_t","ip_b"]};

        padBigLayer.forEach(bigLayer=>{
            if(bigLayer !== "drill"){
                padSmallLayer[bigLayer].forEach(sLayer=>{
                    if(data[bigLayer][sLayer] && data[bigLayer][sLayer].form){
                        this.data[sLayer] = createLayerData(data[bigLayer][sLayer]);
                    }
                })
            }else{
                if(data[bigLayer] instanceof Array){
                    data[bigLayer].forEach(layerData=>{
                        let drillData = {
                            r: layerData.diameter / 2,
                            skewing_x:layerData.offset.x,
                            skewing_y:layerData.offset.y,
                            w: layerData.hole.w,
                            h: layerData.hole.h,
                            form: layerData.hole.form,
                            rotate: layerData.hole.rotate
                        }
                        this.data[bigLayer].push(createLayerData(drillData));
                    });
                }
            }
        });

        function createLayerData(data){
            let figureInstance = self.createLayerIns(data);
            let layerData = {
                offset:{
                    x:data.skewing_x,
                    y:data.skewing_y
                },
                rotate: data.rotate,
                figure:figureInstance
            };
            return layerData;
            
        }
    }

    getDrawData(scale){
        let padSmallLayer = ["b","bs_t","bs_b","bp_t","bp_b","t","ts_t","ts_b","tp_t","tp_b","i","is_t","is_b","ip_t","ip_b","drill"];
        let draw = [];
        padSmallLayer.forEach(layer=>{
            let layerData = this.data[layer];
            if(layer !== "drill"){
                if(layerData && layerData.figure){
                    let drawData = getLayerDrawData(layer,layerData);
                    drawData.fillStyle = styleConfig.pin.color[layer];
                    draw.push(drawData);
                }
            }else{
                layerData.forEach(drill=>{
                    let drawData = getLayerDrawData(layer,drill);
                    drawData.fillStyle = styleConfig.pin.color[layer];
                    draw.push(drawData);
                });
            }
        });
        return draw;
        function getLayerDrawData(layer,layerData){
            if(layerData.figure instanceof BasePath){
                let layerDraw = {
                    layer,
                    data:{
                        path:layerData.figure.getDrawData(scale),
                        skewing_x: layerData.offset.x * scale,
                        skewing_y: -layerData.offset.y * scale,
                        rotate: layerData.rotate,
                        form: "PATH"
                    }
                }
                return layerDraw;
            }else{
                let drawData = layerData.figure.getDrawData(scale);
                drawData.skewing_x = layerData.offset.x * scale;
                drawData.skewing_y = - layerData.offset.y * scale;
                drawData.rotate = layerData.rotate;
                let layerDraw = {
                    data:drawData,
                    layer
                }
                return layerDraw;
            }
        }
    }

    getRange(){
        let padLayer = ["b","bs_t","bs_b","bp_t","bp_b","t","ts_t","ts_b","tp_t","tp_b","i","is_t","is_b","ip_t","ip_b"];
        let range = null;
        padLayer.forEach(layer=>{
            if(this.data[layer]){
                range = computedUtil.compareRange(range,this.data[layer].figure.getRange());
            }
        });
        if(this.data.drill){
            this.data.drill.forEach(dirll=>{
                range = computedUtil.compareRange(range,dirll.figure.getRange());
            })
        }
        return range;
    }

    createLayerIns(data){
        let nameConversion = {CIRCLE:"C",CIRCLE_DRILL:"C",SQUARE:"S",RECTANGLE:"S",RECTANGLE_DRILL:"S",SQUARE_DRILL:"S",OCTAGON:"OC",HOLE_OCTAGON:"OC",OCTAGON_DRILL:"OC",OBLONG_Y:"OV",OVAL:"OV",OBLONG_X:"OV",HOLE_OVAL:"OV",OVAL_DRILL:"OV",OVAL_SLOT:"OV"};
        let form = nameConversion[data.form.toUpperCase()] || data.form.toUpperCase();
        if(form == "C"){
            return new BaseCircle(this.units,data);
        }
        if(form == "S"){
            return new BaseRect(this.units,data);
        }
        if(form == "CS"){
            return new BaseRoundRect(this.units,data);
        }
        if(form == "OV"){
            return new BaseOval(this.units,data);
        }
        if(form == "PATH"){
            return new BasePath(this.units,data.path);
        }
        if(form == "POLY"){
            return new BasePolygon(this.units,data);
        }
    }
}

// 过孔
class VPad extends EPad{
    type = "vpad";

    drillMark = "";

    name = "";

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    setParent(parent){
        this.parent = parent;
    }

    setRawData(padData){
        super.setRawData(padData);
        this.name = padData.name;
        this.drillMark = padData.drillMark;
    }

    getRawData(){
        let rawData = super.getRawData();
        rawData.drillMark = this.drillMark;
        rawData.name = this.name;
        return rawData;
    }
}

class VPin extends Pin{
    type = "via";

    // 网络名称
    networkName = "";

    // 过孔名字
    name = "";

    constructor(units,data){
        super(units);
        if(data){
            this.setRawData(data);
        }
    }

    setParent(parent){
        this.parent = parent;
    }

    setRawData(data){
        super.setRawData(data);
        this.networkName = data.netName;
        this.name = data.name
    }

    getRawData(){
        return {
            x: this.x,
            y: this.y,
            rotate: this.rotate,
            netName: this.networkName,
            name: this.name,
            choose: this.pad.id
        };
    }

    getDrawData(scale){
        // let range = this.getDrawRange(scale);
        // let w = (range.x[1] - range.x[0]) / 2;
        // let h = (range.y[1] - range.y[0]) / 2;

        // if(w < 5 || h < 5){
        //     return [
                
        //     ];
        // }

        let x = this.x * scale, y = this.y * - scale, rotate = this.rotate, num = "";
        let drawPads = this.pad.getDrawData(scale);
        let draw = [];

        drawPads.forEach(drawPad=>{
            drawPad.data.x = x;
            drawPad.data.y = y;
            drawPad.data.pRotate = rotate;
            drawPad.pin_num = num;
            drawPad.type = "pins";
            drawPad.id = this.id;
            draw.push(drawPad);
        });
        return draw;
    }

    setViaDefine(vpad){
        this.pad = vpad;
    }
}

// canvas绘图类
class BaseCanvas{
    /**
     * @type {HTMLCanvasElement}
     */
    canvas = null;

    drawInstance = null;

    origin = {
        x: 0,
        y: 0
    }

    canvasCenter = {
        x: 0,
        y: 0
    }

    width = 0;
    height = 0;

    constructor(options){
        if(!options){
            options = {
                width : 0,
                height : 0
            }
        }
        this.canvas = this.createCanvas(options.width,options.height);
        this.drawInstance = new ImgDraw(this.canvas);
    }

    createCanvas(width,height){
        let canvas = document.createElement("canvas");
        this.width = width || 300;
        this.height = height || 300;
        canvas.width = width;
        canvas.height = height;
        return canvas;
    }

    setCanvasSize(w,h){
        this.width = w;
        this.height = h;
        this.canvas.width = w;
        this.canvas.height = h;
        this.canvasCenter.x = w / 2;
        this.canvasCenter.y = h / 2;
    }

    setCanvasAttr(attr){
        Object.getOwnPropertyNames(attr).forEach(attrname=>{
            let attrData = attr[attrname];
            if(typeof attrData !== "string" && typeof attrData!=="boolean"){
                this.changeElementAttr(this.canvas[attrname],attrData);
                return;
            }
            this.canvas[attrname] = attrData;
        });
    }

    setScale(){}

    // 计算大小

    load(parentNode){
        
    }
}

class ActualCanvas extends BaseCanvas{

    scale = 0.2;

    parentNode = null;

    config = {
        mirror: false
    }

    /**
     * @type {VirtualCanvas []}
     */
    virtualCanvasList = [];

    constructor(parent){
        super();
        this._init();
        this.setOrigin({
            x: this.width / 2,
            y: this.height / 2
        });
        if(parent){
            this.appendTo(parent);
        }
    }

    _init(){
        // 初始化事件监听
        Event.on("wheel",(e)=>{
            let scale = this.scale;

            let mouseSite = this.getMousePoint({
                x: e.clientX,
                y: e.clientY
            });

            let origin = {
                x: this.origin.x,
                y: this.origin.y
            }

            if(this.config.mirror){
                // origin.x = this.canvasSize[0] -  origin.x;
                mouseSite.x = this.canvasSize[0] - mouseSite.x;
            }

            let detail = e.deltaY;
            if(detail < 0){
                // 放大
                scale *= 1.1;

                origin.x = mouseSite.x + (origin.x - mouseSite.x) * 1.1;
                origin.y = mouseSite.y + (origin.y - mouseSite.y) * 1.1;
            }else{
                // 缩小
                scale /= 1.1;
                
                origin.x = mouseSite.x + (origin.x - mouseSite.x) / 1.1;
                origin.y = mouseSite.y + (origin.y - mouseSite.y) / 1.1;
            }
            this.setOrigin(origin);
            this.setScale(scale);
            this.draw();
        });
    }

    setEvent(eventName,callback){
        this.canvas.addEventListener(eventName,callback);
    }

    setScale(scale){
        this.scale = scale;
        this.virtualCanvasList.forEach(vCanvas=>{
            vCanvas.setScale(scale);
            vCanvas.draw()
        });
    }

    // 获取鼠标相对于canvasParent的位置
    getMousePoint(clientPoint){
        var rect = this.canvas.getBoundingClientRect();

        return {
            x: clientPoint.x - rect.left,
            y: clientPoint.y - rect.top
        }
    }

    /**
     * @param {VirtualCanvas} vCanvas 
     */
    addDraw(vCanvas){
        if(!(vCanvas instanceof VirtualCanvas)){
            throw "TypeError:需要 VirtualCanvas, 而传入的是" + vCanvas;
        }
        vCanvas.setActualCanvas(this);
        this.virtualCanvasList.push(vCanvas);
    }

    // 设置原点
    setOrigin(origin){
        this.origin.x = origin.x;
        this.origin.y = origin.y;
        this.drawInstance.setOrigin(origin);
    }

    // 设置父元素
    appendTo(parent){
        if(!(parent instanceof Element) || !(parent instanceof HTMLElement)){
            throw "传入的父节点有误";
        }
        this.parentNode = parent;
        this.parentNode.appendChild(this.canvas);
        this.setCanvasSize(parent.clientWidth,parent.clientHeight);
    }

    // 去中心点
    goCenter(){
        let points = [];
        this.virtualCanvasList.forEach(vCanvas=>{
            points.push(vCanvas.getCenterPoint());
        });
        let center = {
            x: points.reduce((count,point)=>count + point.x,0) / points.length,
            y: points.reduce((count,point)=>count + point.y,0) / points.length
        }
        this.setOrigin({
            x: this.width / 2 - center.x,
            y: this.height / 2 - center.y
        });
        this.draw();
    }

    draw(){
        this.clear();
        this.drawInstance.clearCanvas();
        this.virtualCanvasList.forEach(vCanvas=>{
            let topLeft = vCanvas.topLeft;

            let v2canvasLeft = {
                x: topLeft.x + this.origin.x,
                y: this.origin.y + topLeft.y
            }

            let crossRect = computedUtil.getCrossRect({
                x:0,
                y:0,
                width:this.width,
                height: this.height
            },{
                x: v2canvasLeft.x,
                y: v2canvasLeft.y,
                width: vCanvas.width,
                height: vCanvas.height
            });

            if(!crossRect || !crossRect.width || !crossRect.height){
                return;
            }

            // if(Math.abs(virCanvas.br.x+virCanvas.tl.x-showCanvas.br.x-showCanvas.tl.x) <= (showCanvas.br.x-showCanvas.tl.x + virCanvas.br.x-virCanvas.tl.x)
            //     | Yb2+Yb1-Ya2-Ya1 | <=Y a2-Ya1 + Yb2-Yb1)

            // let v2canvasCenter = {
            //     x: v2canvasLeft.x - this.canvasCenter.x,
            //     y: v2canvasLeft.y - this.canvasCenter.y
            // }
            console.log(crossRect)
            let startTime = new Date().getTime();
            // console.log(startTime)
            // let imgData = vCanvas.drawInstance.WindCtx.getImageData(crossRect.x - v2canvasLeft.x,crossRect.y - v2canvasLeft.y, crossRect.width,crossRect.height);
            // console.log(vCanvas.canvas,{x: crossRect.x - v2canvasLeft.x, y: crossRect.y - v2canvasLeft.y},crossRect.width,crossRect.height,v2canvasLeft,vCanvas.width,vCanvas.height)
            this.drawInstance.drawCanvas(vCanvas.canvas,{x: crossRect.x - v2canvasLeft.x, y: crossRect.y - v2canvasLeft.y},crossRect.width,crossRect.height,{x: crossRect.x - this.origin.x, y: crossRect.y - this.origin.y},crossRect.width,crossRect.height);
            // console.log("需要裁剪的位置",{x: crossRect.x - v2canvasLeft.x, y: crossRect.y - v2canvasLeft.y},"坐标",{x: crossRect.x - this.origin.x, y: crossRect.y - this.origin.y},"canvas大小:",{w:vCanvas.width, h: vCanvas.height})
            // console.log("裁剪耗时：", new Date().getTime() - startTime);
            // console.log(crossRect.x - this.origin.x,crossRect.y - this.origin.y,this.origin,crossRect)
            // this.drawInstance.WindCtx.putImageData(imgData,crossRect.x,  crossRect.y);
        });
        // this.drawInstance.DrawImgAll(this.virtualCanvasList[0].getDrawData());
    }

    clear(){
        this.drawInstance.clearCanvas();
    }
    
}

class VirtualCanvas extends BaseCanvas{

    // 所显示的真实canvas
    /**
     * @type {ActualCanvas}
     */
    actualCanvas = null;

    scale = 1;

    actualOrigin = {
        x: 0,
        y: 0
    }

    /**
     * @type {BaseImage[]}
     */
    diagramList = [];

    // 图形的范围
    diagramRange = {
        x:[0,0],
        y:[0,0]
    };

    // 图形的中心点
    diagramsCenter = {
        x:0,
        y:0
    };

    // canvas左上角相对于原点的位置
    topLeft = {
        x: 0,
        y: 0
    }
    
    constructor(options){
        super(options);
    }

    setDrawData(diagramList){
        this.diagramList = diagramList;
    }

    addDiagrams(dia){
        this.diagramList(dia);
        this.updateCanvasInfo();
    }

    setScale(scale){
        this.scale = scale;
        this.updateCanvasInfo();
    }

    updateCanvasInfo(){
        let sizeInfo = this.getDiagramSizeInfo();


        // 将大小扩大一点
        sizeInfo.w *= 1.2;
        sizeInfo.h *= 1.2;

        this.diagramRange = sizeInfo.range;

        this.diagramsCenter = sizeInfo.center;

        this.setCanvasSize(sizeInfo.w,sizeInfo.h);
        // 重新设置原点 将图形画到正中心
        this.origin.x = sizeInfo.w / 2 - sizeInfo.center.x;
        this.origin.y = sizeInfo.h / 2 - sizeInfo.center.y;
        this.drawInstance.setOrigin({
            x:this.origin.x,
            y:this.origin.y
        });

        this.topLeft.x = sizeInfo.center.x - sizeInfo.w / 2;
        this.topLeft.y = sizeInfo.center.y - sizeInfo.h / 2;

        this.draw();
    }

    // 计算图形的大小以及范围
    getDiagramSizeInfo(){
        let range = null;
        this.diagramList.forEach(img=>{
            if(img.inView(this.actualCanvas.origin,this.scale,this.actualCanvas.width,this.actualCanvas.height)){
                var dirRange = img.getDrawRange(this.scale);
                if(!dirRange){
                    throw img
                }
                range = compareRange(range,dirRange);
            }    
        });
        if(!range){
            range = {
                x:[0,0],
                y:[0,0]
            }
        }
        return {
            range,
            center:{
                x : (range.x[1] + range.x[0]) / 2,
                y : (range.y[1] + range.y[0]) / 2
            },
            w: range.x[1] - range.x[0],
            h: range.y[1] - range.y[0],
        };
        function compareRange(range,toRange){
            if(!toRange){
                return {
                    x:[
                        range.x[0],
                        range.x[1]
                    ],
                    y:[
                        range.y[0],
                        range.y[1]
                    ]
                };
            }
            if(!range){
                return {
                    x:[
                        toRange.x[0],
                        toRange.x[1]
                    ],
                    y:[
                        toRange.y[0],
                        toRange.y[1]
                    ]
                };
            }
            var compare = {
                x:[0,0],
                y:[0,0]
            }
            compare.x[0] = toRange.x[0] < range.x[0] ? toRange.x[0] : range.x[0];
            compare.x[1] = toRange.x[1] > range.x[1] ? toRange.x[1] : range.x[1];
            compare.y[0] = toRange.y[0] < range.y[0] ? toRange.y[0] : range.y[0];
            compare.y[1] = toRange.y[1] > range.y[1] ? toRange.y[1] : range.y[1];
            return compare;
        }
    }
    
    // 获取图形的中心点
    getCenterPoint(){
        return {
            x : this.diagramsCenter.x,
            y : this.diagramsCenter.y
        }
    }

    setActualCanvas(aCanvas){
        this.actualCanvas = aCanvas;
    }

    // 绘图
    draw(drawDdata){
        this.drawInstance.clearCanvas();
        if(drawDdata){
            this.drawInstance.DrawImgAll(drawDdata);
        }else{
            this.drawInstance.DrawImgAll(this.getDrawData());
        }
        // 进行分类
    }

    // 获取绘制的数据
    getDrawData(){
        var drawList = [];
        this.diagramList.forEach(dia=>{
            if(!dia.inView(this.actualCanvas.origin,this.scale,this.actualCanvas.width,this.actualCanvas.height)) return;
            if(dia instanceof EPin){
                drawList.push(...dia.getDrawData(this.scale));
            }else{
                drawList.push(dia.getDrawData(this.scale));
            }
        });

        let pins = [];
        let paths=  [];
        let shapes= [];
        let texts=  [];
        drawList.forEach(item=>{
            if(item.type=="shapes"){
                shapes.push(item);
            }else if(item.type=="paths"){
                paths.push(item);
            }else if(item.type=="texts"){
                texts.push(item);
            }else{
                pins.push(item);
            }
        });
        shapes.sort(function(s1,s2){
            if(s1.make === s2.make){
                return 0;
            }else{
                if(s1.make === "o"){
                    return 1;
                }else{
                    return -1;
                }
            }
        });
        let pinPriority = {b:5,bs_t:3,bs_b:1,bp_t:4,bp_b:2,t:15,ts_t:13,ts_b:11,tp_t:14,tp_b:12,i:10,is_t:8,is_b:6,ip_t:9,ip_b:7,drill:16}
        //"b","bs_t","bs_b","bp_t","bp_b","t","ts_t","ts_b","tp_t","tp_b","i","is_t","is_b","ip_t","ip_b","drill"
        pins.sort(function(p1,p2){
            return pinPriority[p1.layer] - pinPriority[p2.layer];
        });
        // console.log({pins,paths,shapes,texts})
        return {pins,paths,shapes,texts};
    }
}

class PCBCanvas extends BaseCanvas{

    scale = 0.5;

    /**
     * @type {HTMLElement}
     */
    parentNode = null;

    /**
     * @type {VirtualCanvas}
     */
    vCanvas = null;

    /**
     * @type {PCB}
     */
    PCBInstance = null;

    /**
     * @type {DrawPCB}
     */
    drawPCBInstance = null;

    encaList = [];

    viewStatus = {
        device:{
            top:true,
            bottom:false
        },
        trace:{}
    }

    config = {
        mirror: false
    }

    origin = {
        x:0,
        y:0
    }

    constructor(parent){
        super();

        this.vCanvas = new VirtualCanvas();

        this.setOrigin({
            x: this.width / 2,
            y: this.height / 2
        });
        if(parent){
            this.appendTo(parent);
        }
    }

    // 初始化事件
    _init(){
        // 初始化事件监听
        Event.on("wheel",(e)=>{
            let scale = this.scale;

            let mouseSite = this.getMousePoint({
                x: e.clientX,
                y: e.clientY
            });

            let origin = {
                x: this.origin.x,
                y: this.origin.y
            }

            if(this.config.mirror){
                // origin.x = this.canvasSize[0] -  origin.x;
                mouseSite.x = this.canvasSize[0] - mouseSite.x;
            }

            let detail = e.deltaY;
            if(detail < 0){
                // 放大
                scale *= 1.1;

                origin.x = mouseSite.x + (origin.x - mouseSite.x) * 1.1;
                origin.y = mouseSite.y + (origin.y - mouseSite.y) * 1.1;
            }else{
                // 缩小
                scale /= 1.1;
                
                origin.x = mouseSite.x + (origin.x - mouseSite.x) / 1.1;
                origin.y = mouseSite.y + (origin.y - mouseSite.y) / 1.1;
            }

            origin.x = (origin.x + 0.5) | 0;
            origin.y = (origin.y + 0.5) | 0;

            this.setOrigin(origin);
            this.setScale(scale);
            this.drawPcb(this.layer);
        },"pcbCanvasWheel");

        // 鼠标按下事件
        Event.on("mousedown",(e)=>{
            if(e.button === 1){
                let start = {
                    x: e.pageX,
                    y: e.pageY
                };
                let startOrigin = {
                    x: this.origin.x,
                    y: this.origin.y
                };
                let changeOrigin = util.throttle((e)=>{
                    let end = {
                        x: e.pageX,
                        y: e.pageY
                    };
                    let offset = {
                        x: (end.x - start.x) * (this.config.mirror ? -1 : 1),
                        y: end.y - start.y
                    }
                    console.log(startOrigin.x,offset)
                    this.setOrigin({
                        x: startOrigin.x + offset.x,
                        y: startOrigin.y + offset.y,
                    });
                    this.drawPcb(this.layer);
                },16);
                let removeListen = ()=>{
                    window.removeEventListener("mousemove",changeOrigin);
                    window.removeEventListener("mouseup",removeListen);
                }
                window.addEventListener("mousemove",changeOrigin);
                window.addEventListener("mouseup",removeListen);
            }
        },"pcbCanvasMousedown");

        // 鼠标移动事件
        Event.on("mousemove",(e)=>{
            // 获取鼠标位置
            let mousePoint = this.getMousePoint({x: e.clientX, y: e.clientY});

            this.drawPCBInstance.touch(mousePoint)
        });
    }

    // 卸载
    _unload(){
        Event.aliasOff("wheel","pcbCanvasWheel");
        Event.aliasOff("mousedown","pcbCanvasMousedown");
    }

    setPCB(pcb){
        this.PCBInstance = pcb;
    }

    setDrawPcb(drawPcb){
        this.drawPCBInstance = drawPcb;
        this.PCBInstance = this.drawPCBInstance.PCBInstance;
    }

    setEvent(eventName,callback){
        this.canvas.addEventListener(eventName,callback);
    }
    
    setScale(scale){
        this.scale = scale;
    }

    getScale(){
        let scale = this.PCBInstance.units == "mm" ? this.scale * 39.37 : this.scale;
        return this.scale;
    }

    // 设置原点
    setOrigin(origin){
        this.origin.x = Math.floor(origin.x);
        this.origin.y = Math.floor(origin.y);
        this.drawInstance.setOrigin(origin);
        this.vCanvas.drawInstance.setOrigin(origin);
    }

    // 获取原点
    getOrigin(){
        return {
            x: this.origin.x,
            y: this.origin.y
        }
    }

    // 设置父元素
    appendTo(parent){
        if(!(parent instanceof Element) || !(parent instanceof HTMLElement)){
            throw "传入的父节点有误";
        }
        this.parentNode = parent;
        this.parentNode.appendChild(this.canvas);

        // let callback = (mutationList, observer)=>{
        //     this.setCanvasSize(parent.clientWidth,parent.clientHeight);
        //     this.vCanvas.setCanvasSize(parent.clientWidth,parent.clientHeight);
        // }

        // let observerConfig = {attributes :true};

        // if(this.observer){
        //     this.observer.disconnect();
        // }

        // let observer = new MutationObserver(callback);

        // observer.observe(parent,observerConfig);

        // console.log(observer);

        // this.observer = observer;

        this.setCanvasSize(parent.clientWidth,parent.clientHeight);
        this.vCanvas.setCanvasSize(parent.clientWidth,parent.clientHeight);
    }

    // 从父元素移除
    removeTo(){
        if(this.parentNode){
            this.parentNode.removeChild(this.canvas)
        }
    }

    // 绘制
    drawPcb(){
        this.drawInstance.clearCanvas();

        // 获取显示状态
        let viewStatus = this.drawPCBInstance.viewStatus;

        // 判断是否需要绘制格点
        if(viewStatus.other.grid){
            this.drawGrid();
        }

        let scale = this.getScale();


        let drawTraces = [], drawEShapes = [],components = [];

        // 获取需要绘制的电气 走线，铜皮 和元器件
        this.PCBInstance.layerDifinition.etch.forEach(etch=>{
            let layer = etch.name;
            if(viewStatus.etch[layer]){
                if(viewStatus.other.traces){
                    drawTraces.push(this.getLinesDrawData(this.PCBInstance.traces[layer]));
                }else{
                    drawTraces.push([]);
                }
                if(viewStatus.other.electricCopper){
                    drawEShapes.push(this.getCopperDrawData(this.PCBInstance.electricCopper[layer]));
                }else{
                    drawEShapes.push([]);
                }
                components.push(...this.PCBInstance.components.cite[layer])
            }
        });

        let silkScreenLines = [], noetchCooper = [], noetchText = [];

        // 获取需要绘制的丝印线和非电气铜皮
        this.PCBInstance.layerDifinition.noetch.forEach(layer=>{
            if(viewStatus.noetch[layer.name]){
                silkScreenLines.push(this.getLinesDrawData(this.PCBInstance.silkScreenLines[layer.name]));
                noetchCooper.push(this.getCopperDrawData(this.PCBInstance.noelectricCopper[layer.name]));
                noetchText.push(this.getTextDrawData(this.PCBInstance.texts[layer.name]));
                console.log(this.PCBInstance.texts[layer.name])
            }
        });

        let devTime = performance.now(), devNum = 0;

        // 绘制元器件
        components.forEach(device=>{
            // if(device.name !== "D31") return;

            let encaOrigin = {
                x:  device.x * scale,
                y:   - device.y * scale
            }
            
            this.drawInstance.WindCtx.save();

            this.drawInstance.setOrigin(encaOrigin);

            this.drawInstance.WindCtx.rotate(-device.rotate * Math.PI / 180);

            if(viewStatus.other.componentName){
                this.drawInstance.text({
                    content:device.name,
                    x:0,
                    y:0,
                    text_size: 100 * this.getScale()
                });
            }

            let drawObj = this.getEncaDrawData(device,{
                x: this.origin.x + encaOrigin.x,
                y: this.origin.y + encaOrigin.y
            });

            devNum += drawObj.pins.length + drawObj.paths.length + drawObj.shapes.length + drawObj.texts.length;

            this.drawInstance.DrawImgAll(drawObj);

            this.drawInstance.setOrigin({
                x: -encaOrigin.x,
                y: -encaOrigin.y
            });
            this.drawInstance.WindCtx.restore();
        });

        devTime = performance.now() - devTime;

        let traTime = performance.now();   // 统计时间

        // 绘制丝印线和非电气铜皮
        silkScreenLines.forEach((v,i)=>{
            this.vCanvas.draw({paths:silkScreenLines[i],shapes:noetchCooper[i],texts: noetchText[i]});
            this.drawInstance.drawCanvas(this.vCanvas.canvas,{x:-this.origin.x, y:-this.origin.y},this.vCanvas.width,this.vCanvas.height);
        });

        // 绘制电气铜皮和走线
        drawTraces.forEach((v,i)=>{
            this.vCanvas.draw({paths:drawTraces[i],shapes:drawEShapes[i]});
            this.drawInstance.drawCanvas(this.vCanvas.canvas,{x:-this.origin.x, y:-this.origin.y},this.vCanvas.width,this.vCanvas.height);
        });

        traTime = performance.now() - traTime; // 统计时间


        let viaTime = performance.now(); // 统计时间

        let drawVias = [];
        // 是否需要绘制过孔
        if(viewStatus.other.via){
            // 绘制过孔
            drawVias = this.getViaDrawData(this.PCBInstance.vias.cites);
            this.drawInstance.DrawImgAll({pins:drawVias});    
        }

        viaTime = performance.now() - viaTime; // 统计时间

        console.log("元器件图形数量：" + devNum + "，走线图形数量：" + drawTraces.length + "，过孔图形数量：" + drawVias.length);
        console.log("元器件耗时：" + devTime + "ms, 走线耗时：" + traTime + "ms，过孔耗时：" + viaTime + "ms");
        
        this.setOrigin(this.origin);

        // 绘制过孔
    }

    // 绘制格点
    drawGrid(){
        let gridWidth = this.PCBInstance.units == "mm" ? 0.5 : 39.37;
        let scale = this.getScale();
        this.drawInstance.setGrid({
            x: gridWidth * scale,
            y: gridWidth * scale
        });
    }

    // 获取封装的绘图数据
    // 获取绘制的数据
    /**
     * @param {Encapsulation} enca 
     * @param {*} origin 
     * @returns 
     */
    getEncaDrawData(device,origin){
        let enca = device.device.encapsulation;
        var drawList = [];
        let scale = this.getScale();

        enca.diagramList.forEach(dia=>{
            if(!dia.inView(origin,scale,this.width,this.height,-device.rotate)) return;
            let drawData = dia.getDrawData(scale);
            if(drawData instanceof Array){
                drawList.push(...drawData);
            }else{
                drawList.push(drawData);
            }
        });

        let pins = [];
        let paths=  [];
        let shapes= [];
        let texts=  [];
        drawList.forEach(item=>{
            if(item.type=="shapes"){
                shapes.push(item);
            }else if(item.type=="paths"){
                paths.push(item);
            }else if(item.type=="texts"){
                texts.push(item);
            }else{
                pins.push(item);
            }
        });
        shapes.sort(function(s1,s2){
            if(s1.make === s2.make){
                return 0;
            }else{
                if(s1.make === "o"){
                    return 1;
                }else{
                    return -1;
                }
            }
        });
        let pinPriority = {b:5,bs_t:3,bs_b:1,bp_t:4,bp_b:2,t:15,ts_t:13,ts_b:11,tp_t:14,tp_b:12,i:10,is_t:8,is_b:6,ip_t:9,ip_b:7,drill:16}
        //"b","bs_t","bs_b","bp_t","bp_b","t","ts_t","ts_b","tp_t","tp_b","i","is_t","is_b","ip_t","ip_b","drill"
        pins.sort(function(p1,p2){
            return pinPriority[p1.layer] - pinPriority[p2.layer];
        });
        // console.log({pins,paths,shapes,texts})
        return {pins,paths,shapes,texts};
    }

    // 获取线条的绘制数据
    getLinesDrawData(traces){
        if(!traces || !(traces.forEach instanceof Function)){
            return [];
        }
        
        let scale = this.getScale();

        var paths = [];
        traces.forEach(trance=>{
            if(!trance.inView(this.origin,scale,this.width,this.height)) return;
            let drawData = trance.getDrawData(scale);
            if(drawData instanceof Array){
                paths.push(...drawData);
            }else{
                paths.push(drawData);
            }
        });
        return paths;
    }

    // 获取过孔的绘制数据
    getViaDrawData(vias){
        var drawVias = [];
        
        let scale = this.getScale();

        vias.forEach(via=>{
            if(!via.inView(this.origin,scale,this.width,this.height)) return;
            let drawData = via.getDrawData(scale);
            if(drawData instanceof Array){
                drawVias.push(...drawData);
            }else{
                drawVias.push(drawData);
            }
        });
        return drawVias;
    }

    // 获取铜皮的绘制数据
    getCopperDrawData(cCoppers){
        let drawDatas = [];

        let scale = this.getScale();

        cCoppers.forEach(cCopper=>{
            if(!cCopper.inView(this.origin,scale,this.width,this.height)) return;
            let drawData = cCopper.getDrawData(scale);
            if(drawData instanceof Array){
                drawDatas.push(...drawData);
            }else{
                drawDatas.push(drawData);
            }
        });
        return drawDatas;
    }

    // 获取文字的绘制数据
    getTextDrawData(texts){
        let drawDatas = [];

        let scale = this.getScale();

        texts.forEach(text=>{
            if(!text.inView(this.origin,scale,this.width,this.height)) return;
            let drawData = text.getDrawData(scale);
            if(drawData instanceof Array){
                drawDatas.push(...drawData);
            }else{
                drawDatas.push(drawData);
            }
        });

        return drawDatas;
    }
 
    // 获取鼠标相对于canvasParent的位置
    getMousePoint(clientPoint){
        var rect = this.canvas.getBoundingClientRect();

        return {
            x: clientPoint.x - rect.left,
            y: clientPoint.y - rect.top
        }
    }
}